Merge pull request #21902 from compnerd/interpreter-tests
test: port most of the interpreter tests to Windows
diff --git a/benchmark/scripts/test_Benchmark_Driver.py b/benchmark/scripts/test_Benchmark_Driver.py
index 51cc95b..8a75d3a 100644
--- a/benchmark/scripts/test_Benchmark_Driver.py
+++ b/benchmark/scripts/test_Benchmark_Driver.py
@@ -57,13 +57,13 @@
def test_run_benchmarks_by_name_or_ordinal(self):
benchmarks = ['AngryPhonebook', '42']
- self.assertEquals(
+ self.assertEqual(
parse_args(['run'] + benchmarks).benchmarks, benchmarks)
def test_run_benchmarks_matching_pattern(self):
regexes = ['Prefix', '.*Suffix.*']
filters = ['-f', regexes[0], '-f', regexes[1]]
- self.assertEquals(parse_args(['run'] + filters).filters, regexes)
+ self.assertEqual(parse_args(['run'] + filters).filters, regexes)
def test_run_benchmarks_and_filters_are_exclusive(self):
with captured_output() as (_, err):
@@ -76,17 +76,17 @@
def test_tests_location(self):
here = os.path.dirname(os.path.abspath(__file__))
- self.assertEquals(parse_args(['run']).tests, here)
+ self.assertEqual(parse_args(['run']).tests, here)
tests = '/benchmarks/are/here'
- self.assertEquals(parse_args(['run', '-t', tests]).tests, tests)
+ self.assertEqual(parse_args(['run', '-t', tests]).tests, tests)
def test_optimization_argument(self):
- self.assertEquals(parse_args(['run']).optimization, 'O')
- self.assertEquals(
+ self.assertEqual(parse_args(['run']).optimization, 'O')
+ self.assertEqual(
parse_args(['run', '-o', 'O']).optimization, 'O')
- self.assertEquals(
+ self.assertEqual(
parse_args(['run', '-o', 'Onone']).optimization, 'Onone')
- self.assertEquals(
+ self.assertEqual(
parse_args(['run', '-o', 'Osize']).optimization, 'Osize')
with captured_output() as (_, err):
@@ -99,9 +99,9 @@
err.getvalue())
def test_independent_samples(self):
- self.assertEquals(parse_args(['run']).independent_samples, 1)
- self.assertEquals(parse_args(['run', '-i', '3']).independent_samples,
- 3)
+ self.assertEqual(parse_args(['run']).independent_samples, 1)
+ self.assertEqual(parse_args(['run', '-i', '3']).independent_samples,
+ 3)
with captured_output() as (out, err):
self.assertRaises(SystemExit,
parse_args, ['run', '-i', '-3'])
@@ -112,7 +112,7 @@
def test_output_dir(self):
self.assertIsNone(parse_args(['run']).output_dir)
- self.assertEquals(
+ self.assertEqual(
parse_args(['run', '--output-dir', '/log']).output_dir, '/log')
def test_check_supports_vebose_output(self):
@@ -169,12 +169,12 @@
self.subprocess_mock = SubprocessMock()
def test_test_harness(self):
- self.assertEquals(
+ self.assertEqual(
BenchmarkDriver(self.args, tests=['ignored']).test_harness,
'/benchmarks/Benchmark_O')
self.args.tests = '/path'
self.args.optimization = 'Suffix'
- self.assertEquals(
+ self.assertEqual(
BenchmarkDriver(self.args, tests=['ignored']).test_harness,
'/path/Benchmark_Suffix')
@@ -185,10 +185,10 @@
driver = BenchmarkDriver(
self.args, _subprocess=self.subprocess_mock)
self.subprocess_mock.assert_called_all_expected()
- self.assertEquals(driver.tests,
- ['Benchmark1', 'Benchmark2'])
- self.assertEquals(driver.all_tests,
- ['Benchmark1', 'Benchmark2'])
+ self.assertEqual(driver.tests,
+ ['Benchmark1', 'Benchmark2'])
+ self.assertEqual(driver.all_tests,
+ ['Benchmark1', 'Benchmark2'])
self.assertEquals(driver.test_number['Benchmark1'], "1")
self.assertEquals(driver.test_number['Benchmark2'], "2")
@@ -207,9 +207,9 @@
driver = BenchmarkDriver(
self.args, _subprocess=self.subprocess_mock)
self.subprocess_mock.assert_called_all_expected()
- self.assertEquals(driver.tests, ['Benchmark1', 'Benchmark3'])
- self.assertEquals(driver.all_tests,
- ['Benchmark1', 'Benchmark2', 'Benchmark3'])
+ self.assertEqual(driver.tests, ['Benchmark1', 'Benchmark3'])
+ self.assertEqual(driver.all_tests,
+ ['Benchmark1', 'Benchmark2', 'Benchmark3'])
def test_filters_benchmarks_by_pattern(self):
self.args.filters = '-f .+3'.split()
@@ -217,9 +217,9 @@
driver = BenchmarkDriver(
self.args, _subprocess=self.subprocess_mock)
self.subprocess_mock.assert_called_all_expected()
- self.assertEquals(driver.tests, ['Benchmark3'])
- self.assertEquals(driver.all_tests,
- ['Benchmark1', 'Benchmark2', 'Benchmark3'])
+ self.assertEqual(driver.tests, ['Benchmark3'])
+ self.assertEqual(driver.all_tests,
+ ['Benchmark1', 'Benchmark2', 'Benchmark3'])
def test_log_file(self):
"""When swift-repo is set, log is tied to Git branch and revision."""
@@ -230,8 +230,8 @@
driver = BenchmarkDriver(
Stub(output_dir='/path', tests='/bin/', optimization='Suffix',
swift_repo=None,), tests=['ignored'])
- self.assertEquals(driver.log_file,
- '/path/Benchmark_Suffix-' + now + '.log')
+ self.assertEqual(driver.log_file,
+ '/path/Benchmark_Suffix-' + now + '.log')
r = '/repo/'
subprocess_mock = SubprocessMock(responses=[
@@ -243,8 +243,8 @@
driver = BenchmarkDriver(
Stub(output_dir='/log/', tests='', optimization='S', swift_repo=r),
tests=['ignored'], _subprocess=subprocess_mock)
- self.assertEquals(driver.log_file,
- '/log/branch/Benchmark_S-' + now + '-short_hash.log')
+ self.assertEqual(driver.log_file,
+ '/log/branch/Benchmark_S-' + now + '-short_hash.log')
subprocess_mock.assert_called_all_expected()
@@ -332,14 +332,14 @@
"""Extract up to 20 measurements from an independent run."""
self.driver.args.independent_samples = 3
r = self.driver.run_independent_samples('b1')
- self.assertEquals(self.subprocess_mock.calls.count(
+ self.assertEqual(self.subprocess_mock.calls.count(
('/benchmarks/Benchmark_O', 'b1', '--num-iters=1', '--memory',
'--quantile=20', '--delta')), 3)
- self.assertEquals(r.num_samples, 3) # results are merged
+ self.assertEqual(r.num_samples, 3) # results are merged
def test_run_and_log(self):
def mock_run(test):
- self.assertEquals(test, 'b1')
+ self.assertEqual(test, 'b1')
return PerformanceTestResult(
'3,b1,5,101,1,1,1,1,888'.split(','),
quantiles=True, delta=True, memory=True)
@@ -352,8 +352,8 @@
header = '#,TEST,SAMPLES,MIN(μs),Q1(μs),MEDIAN(μs),Q3(μs),MAX(μs),' +\
'MAX_RSS(B)\n'
csv_log = '3,b1,5,101,102,103,104,105,888\n'
- self.assertEquals(log, None)
- self.assertEquals(
+ self.assertEqual(log, None)
+ self.assertEqual(
out.getvalue(),
header +
csv_log +
@@ -363,8 +363,8 @@
with captured_output() as (out, _):
log = driver.run_and_log(csv_console=False)
- self.assertEquals(log, header + csv_log)
- self.assertEquals(
+ self.assertEqual(log, header + csv_log)
+ self.assertEqual(
out.getvalue(),
' # TEST SAMPLES MIN(μs) Q1(μs)' +
' MEDIAN(μs) Q3(μs) MAX(μs) MAX_RSS(B)\n' +
@@ -376,11 +376,11 @@
def test_log_results(self):
"""Create log directory if it doesn't exist and write the log file."""
def assert_log_written(out, log_file, content):
- self.assertEquals(out.getvalue(),
- 'Logging results to: ' + log_file + '\n')
+ self.assertEqual(out.getvalue(),
+ 'Logging results to: ' + log_file + '\n')
with open(log_file, 'rU') as f:
text = f.read()
- self.assertEquals(text, "formatted output")
+ self.assertEqual(text, "formatted output")
try:
import tempfile # setUp
@@ -408,7 +408,7 @@
def test_deterministing_hashing(self):
cmd = ['printenv', 'SWIFT_DETERMINISTIC_HASHING']
driver = BenchmarkDriver(['no args'], tests=['ignored'])
- self.assertEquals(driver._invoke(cmd).strip(), '1')
+ self.assertEqual(driver._invoke(cmd).strip(), '1')
class BenchmarkDriverMock(Mock):
@@ -437,7 +437,7 @@
'name': 'Base.category', 'level': logging.DEBUG,
'levelname': 'DEBUG', 'msg': 'Hi!'})
f = LoggingReportFormatter()
- self.assertEquals(f.format(lr), 'DEBUG category: Hi!')
+ self.assertEqual(f.format(lr), 'DEBUG category: Hi!')
def test_colored_log_format(self):
def record(level, level_name):
@@ -445,23 +445,23 @@
'name': 'Base.category', 'levelno': level,
'levelname': level_name, 'msg': 'Hi!'})
f = LoggingReportFormatter(use_color=True)
- self.assertEquals(f.format(record(logging.DEBUG, 'DEBUG')),
- '\x1b[1;39mcategory: Hi!\x1b[1;0m')
- self.assertEquals(f.format(record(logging.INFO, 'INFO')),
- '\x1b[1;32mcategory: Hi!\x1b[1;0m')
- self.assertEquals(f.format(record(logging.WARNING, 'WARNING')),
- '\x1b[1;33mcategory: Hi!\x1b[1;0m')
- self.assertEquals(f.format(record(logging.ERROR, 'ERROR')),
- '\x1b[1;31mcategory: Hi!\x1b[1;0m')
- self.assertEquals(f.format(record(logging.CRITICAL, 'CRITICAL')),
- '\x1b[1;35mcategory: Hi!\x1b[1;0m')
+ self.assertEqual(f.format(record(logging.DEBUG, 'DEBUG')),
+ '\x1b[1;39mcategory: Hi!\x1b[1;0m')
+ self.assertEqual(f.format(record(logging.INFO, 'INFO')),
+ '\x1b[1;32mcategory: Hi!\x1b[1;0m')
+ self.assertEqual(f.format(record(logging.WARNING, 'WARNING')),
+ '\x1b[1;33mcategory: Hi!\x1b[1;0m')
+ self.assertEqual(f.format(record(logging.ERROR, 'ERROR')),
+ '\x1b[1;31mcategory: Hi!\x1b[1;0m')
+ self.assertEqual(f.format(record(logging.CRITICAL, 'CRITICAL')),
+ '\x1b[1;35mcategory: Hi!\x1b[1;0m')
def test_no_prefix_for_base_logging(self):
lr = logging.makeLogRecord({
'name': 'Base', 'level': logging.INFO,
'levelname': 'INFO', 'msg': 'Hi!'})
f = LoggingReportFormatter()
- self.assertEquals(f.format(lr), 'INFO Hi!')
+ self.assertEqual(f.format(lr), 'INFO Hi!')
class TestMarkdownReportHandler(unittest.TestCase):
@@ -481,7 +481,7 @@
'levelno': level, 'msg': msg})
def test_init_writes_table_header(self):
- self.assertEquals(self.handler.level, logging.INFO)
+ self.assertEqual(self.handler.level, logging.INFO)
self.assert_contains(['Benchmark Check Report\n', '---|---'])
def test_close_writes_final_newlines(self):
@@ -552,7 +552,7 @@
with captured_output() as (out, _):
BenchmarkDoctor(self.args, driver)
self.assert_contains(['Checking tests: B1, B2'], self.logs['debug'])
- self.assertEquals(out.getvalue(), '')
+ self.assertEqual(out.getvalue(), '')
def test_supports_verbose_output(self):
driver = BenchmarkDriverMock(tests=['B1', 'B2'])
@@ -607,7 +607,7 @@
'B1 O i1a', 'B1 O i1b', 'B1 O i1c', 'B1 O i1d', 'B1 O i1e',
'B1 O i2a', 'B1 O i2b', 'B1 O i2c', 'B1 O i2d', 'B1 O i2e'],
measurements.keys())
- self.assertEquals(measurements['name'], 'B1')
+ self.assertEqual(measurements['name'], 'B1')
self.assert_contains(
['Calibrating num-samples for B1:',
'Runtime 300 μs yields 4096 adjusted samples per second.',
diff --git a/benchmark/scripts/test_compare_perf_tests.py b/benchmark/scripts/test_compare_perf_tests.py
index 04af04c..6ac0a33 100644
--- a/benchmark/scripts/test_compare_perf_tests.py
+++ b/benchmark/scripts/test_compare_perf_tests.py
@@ -35,15 +35,15 @@
class TestSample(unittest.TestCase):
def test_has_named_fields(self):
s = Sample(1, 2, 3)
- self.assertEquals(s.i, 1)
- self.assertEquals(s.num_iters, 2)
- self.assertEquals(s.runtime, 3)
+ self.assertEqual(s.i, 1)
+ self.assertEqual(s.num_iters, 2)
+ self.assertEqual(s.runtime, 3)
def test_is_iterable(self):
s = Sample(1, 2, 3)
- self.assertEquals(s[0], 1)
- self.assertEquals(s[1], 2)
- self.assertEquals(s[2], 3)
+ self.assertEqual(s[0], 1)
+ self.assertEqual(s[1], 2)
+ self.assertEqual(s[2], 3)
class TestPerformanceTestSamples(unittest.TestCase):
@@ -52,34 +52,34 @@
self.samples.add(Sample(7, 42, 1000))
def test_has_name(self):
- self.assertEquals(self.samples.name, 'B1')
+ self.assertEqual(self.samples.name, 'B1')
def test_stores_samples(self):
- self.assertEquals(self.samples.count, 1)
+ self.assertEqual(self.samples.count, 1)
s = self.samples.samples[0]
self.assertTrue(isinstance(s, Sample))
- self.assertEquals(s.i, 7)
- self.assertEquals(s.num_iters, 42)
- self.assertEquals(s.runtime, 1000)
+ self.assertEqual(s.i, 7)
+ self.assertEqual(s.num_iters, 42)
+ self.assertEqual(s.runtime, 1000)
def test_quantile(self):
- self.assertEquals(self.samples.quantile(1), 1000)
- self.assertEquals(self.samples.quantile(0), 1000)
+ self.assertEqual(self.samples.quantile(1), 1000)
+ self.assertEqual(self.samples.quantile(0), 1000)
self.samples.add(Sample(2, 1, 1100))
- self.assertEquals(self.samples.quantile(0), 1000)
- self.assertEquals(self.samples.quantile(1), 1100)
+ self.assertEqual(self.samples.quantile(0), 1000)
+ self.assertEqual(self.samples.quantile(1), 1100)
self.samples.add(Sample(3, 1, 1050))
- self.assertEquals(self.samples.quantile(0), 1000)
- self.assertEquals(self.samples.quantile(.5), 1050)
- self.assertEquals(self.samples.quantile(1), 1100)
+ self.assertEqual(self.samples.quantile(0), 1000)
+ self.assertEqual(self.samples.quantile(.5), 1050)
+ self.assertEqual(self.samples.quantile(1), 1100)
def assertEqualFiveNumberSummary(self, ss, expected_fns):
e_min, e_q1, e_median, e_q3, e_max = expected_fns
- self.assertEquals(ss.min, e_min)
- self.assertEquals(ss.q1, e_q1)
- self.assertEquals(ss.median, e_median)
- self.assertEquals(ss.q3, e_q3)
- self.assertEquals(ss.max, e_max)
+ self.assertEqual(ss.min, e_min)
+ self.assertEqual(ss.q1, e_q1)
+ self.assertEqual(ss.median, e_median)
+ self.assertEqual(ss.q3, e_q3)
+ self.assertEqual(ss.max, e_max)
def test_computes_five_number_summary(self):
self.assertEqualFiveNumberSummary(
@@ -98,38 +98,38 @@
self.samples, (1000, 1025, 1050, 1075, 1100))
def test_computes_inter_quartile_range(self):
- self.assertEquals(self.samples.iqr, 0)
+ self.assertEqual(self.samples.iqr, 0)
self.samples.add(Sample(2, 1, 1025))
self.samples.add(Sample(3, 1, 1050))
self.samples.add(Sample(4, 1, 1075))
self.samples.add(Sample(5, 1, 1100))
- self.assertEquals(self.samples.iqr, 50)
+ self.assertEqual(self.samples.iqr, 50)
- def assertEqualStats(self, stats, expected_stats):
+ def assertEqualtats(self, stats, expected_stats):
for actual, expected in zip(stats, expected_stats):
self.assertAlmostEquals(actual, expected, places=2)
def test_computes_mean_sd_cv(self):
ss = self.samples
- self.assertEqualStats(
+ self.assertEqualtats(
(ss.mean, ss.sd, ss.cv), (1000.0, 0.0, 0.0))
self.samples.add(Sample(2, 1, 1100))
- self.assertEqualStats(
+ self.assertEqualtats(
(ss.mean, ss.sd, ss.cv), (1050.0, 70.71, 6.7 / 100))
def test_computes_range_spread(self):
ss = self.samples
- self.assertEqualStats(
+ self.assertEqualtats(
(ss.range, ss.spread), (0, 0))
self.samples.add(Sample(2, 1, 1100))
- self.assertEqualStats(
+ self.assertEqualtats(
(ss.range, ss.spread), (100, 10.0 / 100))
def test_init_with_samples(self):
self.samples = PerformanceTestSamples(
'B2', [Sample(0, 1, 1000), Sample(1, 1, 1100)])
- self.assertEquals(self.samples.count, 2)
- self.assertEqualStats(
+ self.assertEqual(self.samples.count, 2)
+ self.assertEqualtats(
(self.samples.mean, self.samples.sd,
self.samples.range, self.samples.spread),
(1050.0, 70.71, 100, 9.52 / 100))
@@ -138,7 +138,7 @@
# guard against dividing by 0
self.samples = PerformanceTestSamples('Zero')
self.samples.add(Sample(0, 1, 0))
- self.assertEqualStats(
+ self.assertEqualtats(
(self.samples.mean, self.samples.sd, self.samples.cv,
self.samples.range, self.samples.spread),
(0, 0, 0.0, 0, 0.0))
@@ -149,17 +149,17 @@
'5 1 1000, 6 1 1025, 7 1 1050, 8 1 1075, 9 1 1100, '
'10 1 1050, 11 1 949, 12 1 1151'.split(',')]
self.samples = PerformanceTestSamples('Outliers', ss)
- self.assertEquals(self.samples.count, 13)
- self.assertEqualStats(
+ self.assertEqual(self.samples.count, 13)
+ self.assertEqualtats(
(self.samples.mean, self.samples.sd), (1050, 52.36))
self.samples.exclude_outliers()
- self.assertEquals(self.samples.count, 11)
- self.assertEquals(self.samples.outliers, ss[11:])
+ self.assertEqual(self.samples.count, 11)
+ self.assertEqual(self.samples.outliers, ss[11:])
self.assertEqualFiveNumberSummary(
self.samples, (1000, 1025, 1050, 1075, 1100))
- self.assertEqualStats(
+ self.assertEqualtats(
(self.samples.mean, self.samples.sd), (1050, 35.36))
def test_excludes_outliers_zero_IQR(self):
@@ -168,12 +168,12 @@
self.samples.add(Sample(1, 2, 18))
self.samples.add(Sample(2, 2, 18))
self.samples.add(Sample(3, 2, 18))
- self.assertEquals(self.samples.iqr, 0)
+ self.assertEqual(self.samples.iqr, 0)
self.samples.exclude_outliers()
- self.assertEquals(self.samples.count, 3)
- self.assertEqualStats(
+ self.assertEqual(self.samples.count, 3)
+ self.assertEqualtats(
(self.samples.min, self.samples.max), (18, 18))
def test_excludes_outliers_top_only(self):
@@ -181,61 +181,61 @@
'0 1 1, 1 1 2, 2 1 2, 3 1 2, 4 1 3'.split(',')]
self.samples = PerformanceTestSamples('Top', ss)
self.assertEqualFiveNumberSummary(self.samples, (1, 2, 2, 2, 3))
- self.assertEquals(self.samples.iqr, 0)
+ self.assertEqual(self.samples.iqr, 0)
self.samples.exclude_outliers(top_only=True)
- self.assertEquals(self.samples.count, 4)
- self.assertEqualStats((self.samples.min, self.samples.max), (1, 2))
+ self.assertEqual(self.samples.count, 4)
+ self.assertEqualtats((self.samples.min, self.samples.max), (1, 2))
class TestPerformanceTestResult(unittest.TestCase):
def test_init(self):
log_line = '1,AngryPhonebook,20,10664,12933,11035,576,10884'
r = PerformanceTestResult(log_line.split(','))
- self.assertEquals(r.test_num, '1')
- self.assertEquals(r.name, 'AngryPhonebook')
- self.assertEquals(
+ self.assertEqual(r.test_num, '1')
+ self.assertEqual(r.name, 'AngryPhonebook')
+ self.assertEqual(
(r.num_samples, r.min, r.max, r.mean, r.sd, r.median),
(20, 10664, 12933, 11035, 576, 10884))
- self.assertEquals(r.samples, None)
+ self.assertEqual(r.samples, None)
log_line = '1,AngryPhonebook,1,12045,12045,12045,0,12045,10510336'
r = PerformanceTestResult(log_line.split(','))
- self.assertEquals(r.max_rss, 10510336)
+ self.assertEqual(r.max_rss, 10510336)
def test_init_quantiles(self):
# #,TEST,SAMPLES,MIN(μs),MEDIAN(μs),MAX(μs)
log = '1,Ackermann,3,54383,54512,54601'
r = PerformanceTestResult(log.split(','), quantiles=True)
- self.assertEquals(r.test_num, '1')
- self.assertEquals(r.name, 'Ackermann')
- self.assertEquals((r.num_samples, r.min, r.median, r.max),
- (3, 54383, 54512, 54601))
+ self.assertEqual(r.test_num, '1')
+ self.assertEqual(r.name, 'Ackermann')
+ self.assertEqual((r.num_samples, r.min, r.median, r.max),
+ (3, 54383, 54512, 54601))
self.assertAlmostEquals(r.mean, 54498.67, places=2)
self.assertAlmostEquals(r.sd, 109.61, places=2)
- self.assertEquals(r.samples.count, 3)
- self.assertEquals(r.samples.num_samples, 3)
- self.assertEquals([s.runtime for s in r.samples.all_samples],
- [54383, 54512, 54601])
+ self.assertEqual(r.samples.count, 3)
+ self.assertEqual(r.samples.num_samples, 3)
+ self.assertEqual([s.runtime for s in r.samples.all_samples],
+ [54383, 54512, 54601])
# #,TEST,SAMPLES,MIN(μs),MEDIAN(μs),MAX(μs),MAX_RSS(B)
log = '1,Ackermann,3,54529,54760,55807,266240'
r = PerformanceTestResult(log.split(','), quantiles=True, memory=True)
- self.assertEquals((r.samples.count, r.max_rss), (3, 266240))
+ self.assertEqual((r.samples.count, r.max_rss), (3, 266240))
# #,TEST,SAMPLES,MIN(μs),Q1(μs),Q2(μs),Q3(μs),MAX(μs)
log = '1,Ackermann,5,54570,54593,54644,57212,58304'
r = PerformanceTestResult(log.split(','), quantiles=True, memory=False)
- self.assertEquals((r.num_samples, r.min, r.median, r.max),
- (5, 54570, 54644, 58304))
- self.assertEquals((r.samples.q1, r.samples.q3), (54593, 57212))
- self.assertEquals(r.samples.count, 5)
+ self.assertEqual((r.num_samples, r.min, r.median, r.max),
+ (5, 54570, 54644, 58304))
+ self.assertEqual((r.samples.q1, r.samples.q3), (54593, 57212))
+ self.assertEqual(r.samples.count, 5)
# #,TEST,SAMPLES,MIN(μs),Q1(μs),Q2(μs),Q3(μs),MAX(μs),MAX_RSS(B)
log = '1,Ackermann,5,54686,54731,54774,55030,63466,270336'
r = PerformanceTestResult(log.split(','), quantiles=True, memory=True)
- self.assertEquals(r.samples.num_samples, 5)
- self.assertEquals(r.samples.count, 4) # outlier was excluded
- self.assertEquals(r.max_rss, 270336)
+ self.assertEqual(r.samples.num_samples, 5)
+ self.assertEqual(r.samples.count, 4) # outlier was excluded
+ self.assertEqual(r.max_rss, 270336)
def test_init_delta_quantiles(self):
# #,TEST,SAMPLES,MIN(μs),𝚫MEDIAN,𝚫MAX
@@ -243,10 +243,10 @@
# the difference is 0, which is ommited -- only separator remains
log = '202,DropWhileArray,2,265,,22'
r = PerformanceTestResult(log.split(','), quantiles=True, delta=True)
- self.assertEquals((r.num_samples, r.min, r.median, r.max),
- (2, 265, 265, 287))
- self.assertEquals(r.samples.count, 2)
- self.assertEquals(r.samples.num_samples, 2)
+ self.assertEqual((r.num_samples, r.min, r.median, r.max),
+ (2, 265, 265, 287))
+ self.assertEqual(r.samples.count, 2)
+ self.assertEqual(r.samples.num_samples, 2)
def test_init_oversampled_quantiles(self):
"""When num_samples is < quantile + 1, some of the measurements are
@@ -265,9 +265,9 @@
num_samples = deq.count('1')
r = PerformanceTestResult(['0', 'B', str(num_samples)] + deq,
quantiles=True, delta=True)
- self.assertEquals(r.samples.num_samples, num_samples)
- self.assertEquals([s.runtime for s in r.samples.all_samples],
- range(1, num_samples + 1))
+ self.assertEqual(r.samples.num_samples, num_samples)
+ self.assertEqual([s.runtime for s in r.samples.all_samples],
+ range(1, num_samples + 1))
delta_encoded_quantiles = """
1,,
@@ -311,7 +311,7 @@
def test_repr(self):
log_line = '1,AngryPhonebook,20,10664,12933,11035,576,10884'
r = PerformanceTestResult(log_line.split(','))
- self.assertEquals(
+ self.assertEqual(
str(r),
'<PerformanceTestResult name:\'AngryPhonebook\' samples:20 '
'min:10664 max:12933 mean:11035 sd:576 median:10884>'
@@ -333,17 +333,17 @@
r.sd, r.median, r.max_rss, r.setup)
r = results[0]
- self.assertEquals(as_tuple(r),
- (1, 12045, 12045, 12045, 0, 12045, None, None))
+ self.assertEqual(as_tuple(r),
+ (1, 12045, 12045, 12045, 0, 12045, None, None))
r.merge(results[1])
- self.assertEquals(as_tuple(r), # drops SD and median, +max_rss
- (2, 12045, 12325, 12185, None, None, 10510336, None))
+ self.assertEqual(as_tuple(r), # drops SD and median, +max_rss
+ (2, 12045, 12325, 12185, None, None, 10510336, None))
r.merge(results[2])
- self.assertEquals(as_tuple(r), # picks smaller of the MAX_RSS, +setup
- (3, 11616, 12325, 11995.33, None, None, 10502144, 9))
+ self.assertEqual(as_tuple(r), # picks smaller of the MAX_RSS, +setup
+ (3, 11616, 12325, 11995.33, None, None, 10502144, 9))
r.merge(results[3])
- self.assertEquals(as_tuple(r), # picks smaller of the setup values
- (4, 11616, 12325, 12064, None, None, 10498048, 7))
+ self.assertEqual(as_tuple(r), # picks smaller of the setup values
+ (4, 11616, 12325, 12064, None, None, 10498048, 7))
class TestResultComparison(unittest.TestCase):
@@ -359,14 +359,14 @@
def test_init(self):
rc = ResultComparison(self.r1, self.r2)
- self.assertEquals(rc.name, 'AngryPhonebook')
+ self.assertEqual(rc.name, 'AngryPhonebook')
self.assertAlmostEquals(rc.ratio, 12325.0 / 11616.0)
self.assertAlmostEquals(rc.delta, (((11616.0 / 12325.0) - 1) * 100),
places=3)
# handle test results that sometimes change to zero, when compiler
# optimizes out the body of the incorrectly written test
rc = ResultComparison(self.r0, self.r0)
- self.assertEquals(rc.name, 'GlobalClass')
+ self.assertEqual(rc.name, 'GlobalClass')
self.assertAlmostEquals(rc.ratio, 1)
self.assertAlmostEquals(rc.delta, 0, places=3)
rc = ResultComparison(self.r0, self.r01)
@@ -452,14 +452,14 @@
parser = LogParser()
results = parser.parse_results(log.splitlines())
self.assertTrue(isinstance(results[0], PerformanceTestResult))
- self.assertEquals(results[0].name, 'BitCount')
+ self.assertEqual(results[0].name, 'BitCount')
def test_parse_results_tab_delimited(self):
log = '34\tBitCount\t20\t3\t4\t4\t0\t4'
parser = LogParser()
results = parser.parse_results(log.splitlines())
self.assertTrue(isinstance(results[0], PerformanceTestResult))
- self.assertEquals(results[0].name, 'BitCount')
+ self.assertEqual(results[0].name, 'BitCount')
def test_parse_results_formatted_text(self):
"""Parse format that Benchmark_Driver prints to console"""
@@ -473,32 +473,32 @@
results = parser.parse_results(log.splitlines()[1:]) # without 1st \n
self.assertTrue(isinstance(results[0], PerformanceTestResult))
r = results[0]
- self.assertEquals(r.name, 'Array2D')
- self.assertEquals(r.max_rss, 20915200)
+ self.assertEqual(r.name, 'Array2D')
+ self.assertEqual(r.max_rss, 20915200)
def test_parse_quantiles(self):
"""Gathers samples from reported quantiles. Handles optional memory."""
r = LogParser.results_from_string(
"""#,TEST,SAMPLES,MIN(μs),MEDIAN(μs),MAX(μs)
1,Ackermann,3,54383,54512,54601""")['Ackermann']
- self.assertEquals([s.runtime for s in r.samples.all_samples],
- [54383, 54512, 54601])
+ self.assertEqual([s.runtime for s in r.samples.all_samples],
+ [54383, 54512, 54601])
r = LogParser.results_from_string(
"""#,TEST,SAMPLES,MIN(μs),MEDIAN(μs),MAX(μs),MAX_RSS(B)
1,Ackermann,3,54529,54760,55807,266240""")['Ackermann']
- self.assertEquals([s.runtime for s in r.samples.all_samples],
- [54529, 54760, 55807])
- self.assertEquals(r.max_rss, 266240)
+ self.assertEqual([s.runtime for s in r.samples.all_samples],
+ [54529, 54760, 55807])
+ self.assertEqual(r.max_rss, 266240)
def test_parse_delta_quantiles(self):
r = LogParser.results_from_string( # 2-quantile aka. median
'#,TEST,SAMPLES,MIN(μs),𝚫MEDIAN,𝚫MAX\n0,B,1,101,,')['B']
- self.assertEquals(
+ self.assertEqual(
(r.num_samples, r.min, r.median, r.max, r.samples.count),
(1, 101, 101, 101, 1))
r = LogParser.results_from_string(
'#,TEST,SAMPLES,MIN(μs),𝚫MEDIAN,𝚫MAX\n0,B,2,101,,1')['B']
- self.assertEquals(
+ self.assertEqual(
(r.num_samples, r.min, r.median, r.max, r.samples.count),
(2, 101, 101, 102, 2))
r = LogParser.results_from_string( # 20-quantiles aka. ventiles
@@ -506,7 +506,7 @@
'𝚫V9,𝚫VA,𝚫VB,𝚫VC,𝚫VD,𝚫VE,𝚫VF,𝚫VG,𝚫VH,𝚫VI,𝚫VJ,𝚫MAX\n' +
'202,DropWhileArray,200,214,,,,,,,,,,,,1,,,,,,2,16,464'
)['DropWhileArray']
- self.assertEquals(
+ self.assertEqual(
(r.num_samples, r.min, r.max, r.samples.count),
# last 3 ventiles were outliers and were excluded from the sample
(200, 214, 215, 18))
@@ -538,28 +538,28 @@
results = parser.parse_results(verbose_log.split('\n'))
r = results[0]
- self.assertEquals(
+ self.assertEqual(
(r.name, r.min, r.max, int(r.mean), int(r.sd), r.median),
('AngryPhonebook', 11467, 13898, 12392, 1315, 11812)
)
- self.assertEquals(r.num_samples, r.samples.num_samples)
- self.assertEquals(results[0].samples.all_samples,
- [(0, 78, 11812), (1, 90, 13898), (2, 90, 11467)])
- self.assertEquals(r.yields, None)
+ self.assertEqual(r.num_samples, r.samples.num_samples)
+ self.assertEqual(results[0].samples.all_samples,
+ [(0, 78, 11812), (1, 90, 13898), (2, 90, 11467)])
+ self.assertEqual(r.yields, None)
r = results[1]
- self.assertEquals(
+ self.assertEqual(
(r.name, r.min, r.max, int(r.mean), int(r.sd), r.median),
('Array2D', 369900, 381039, 373994, 6127, 371043)
)
- self.assertEquals(r.setup, 14444)
- self.assertEquals(r.num_samples, r.samples.num_samples)
- self.assertEquals(results[1].samples.all_samples,
- [(0, 1, 369900), (1, 1, 381039), (2, 1, 371043)])
+ self.assertEqual(r.setup, 14444)
+ self.assertEqual(r.num_samples, r.samples.num_samples)
+ self.assertEqual(results[1].samples.all_samples,
+ [(0, 1, 369900), (1, 1, 381039), (2, 1, 371043)])
yielded = r.yields[0]
- self.assertEquals(yielded.before_sample, 1)
- self.assertEquals(yielded.after, 369918)
- self.assertEquals(r.yields, [(1, 369918), (2, 381039)])
+ self.assertEqual(yielded.before_sample, 1)
+ self.assertEqual(yielded.after, 369918)
+ self.assertEqual(r.yields, [(1, 369918), (2, 381039)])
def test_parse_environment_verbose(self):
"""Parse stats about environment in verbose mode."""
@@ -572,21 +572,21 @@
results = parser.parse_results(verbose_log.split('\n'))
r = results[0]
- self.assertEquals(r.max_rss, 32768)
- self.assertEquals(r.mem_pages, 8)
- self.assertEquals(r.voluntary_cs, 1)
- self.assertEquals(r.involuntary_cs, 1109)
+ self.assertEqual(r.max_rss, 32768)
+ self.assertEqual(r.mem_pages, 8)
+ self.assertEqual(r.voluntary_cs, 1)
+ self.assertEqual(r.involuntary_cs, 1109)
def test_results_from_merge(self):
"""Parsing concatenated log merges same PerformanceTestResults"""
concatenated_logs = """4,ArrayAppend,20,23641,29000,24990,0,24990
4,ArrayAppend,1,20000,20000,20000,0,20000"""
results = LogParser.results_from_string(concatenated_logs)
- self.assertEquals(results.keys(), ['ArrayAppend'])
+ self.assertEqual(results.keys(), ['ArrayAppend'])
result = results['ArrayAppend']
self.assertTrue(isinstance(result, PerformanceTestResult))
- self.assertEquals(result.min, 20000)
- self.assertEquals(result.max, 29000)
+ self.assertEqual(result.min, 20000)
+ self.assertEqual(result.max, 29000)
def test_results_from_merge_verbose(self):
"""Parsing verbose log merges all PerformanceTestSamples.
@@ -604,18 +604,18 @@
Sample 3,364245
3,Array2D,4,363094,376131,368159,5931,369169"""
results = LogParser.results_from_string(concatenated_logs)
- self.assertEquals(results.keys(), ['Array2D'])
+ self.assertEqual(results.keys(), ['Array2D'])
result = results['Array2D']
self.assertTrue(isinstance(result, PerformanceTestResult))
- self.assertEquals(result.min, 350815)
- self.assertEquals(result.max, 376131)
- self.assertEquals(result.median, 358817)
+ self.assertEqual(result.min, 350815)
+ self.assertEqual(result.max, 376131)
+ self.assertEqual(result.median, 358817)
self.assertAlmostEquals(result.sd, 8443.37, places=2)
self.assertAlmostEquals(result.mean, 361463.25, places=2)
- self.assertEquals(result.num_samples, 8)
+ self.assertEqual(result.num_samples, 8)
samples = result.samples
self.assertTrue(isinstance(samples, PerformanceTestSamples))
- self.assertEquals(samples.count, 8)
+ self.assertEqual(samples.count, 8)
def test_excludes_outliers_from_samples(self):
verbose_log = """Running DropFirstAnySeqCntRangeLazy for 10 samples.
@@ -643,9 +643,9 @@
"""
parser = LogParser()
result = parser.parse_results(verbose_log.split('\n'))[0]
- self.assertEquals(result.num_samples, 10)
- self.assertEquals(result.samples.count, 8)
- self.assertEquals(len(result.samples.outliers), 2)
+ self.assertEqual(result.num_samples, 10)
+ self.assertEqual(result.samples.count, 8)
+ self.assertEqual(len(result.samples.outliers), 2)
class TestTestComparator(OldAndNewLog):
@@ -654,27 +654,27 @@
return [t.name for t in tests]
tc = TestComparator(self.old_results, self.new_results, 0.05)
- self.assertEquals(names(tc.unchanged), ['AngryPhonebook', 'Array2D'])
- self.assertEquals(names(tc.increased), ['ByteSwap', 'ArrayAppend'])
- self.assertEquals(names(tc.decreased), ['BitCount'])
- self.assertEquals(names(tc.added), ['TwoSum'])
- self.assertEquals(names(tc.removed), ['AnyHashableWithAClass'])
+ self.assertEqual(names(tc.unchanged), ['AngryPhonebook', 'Array2D'])
+ self.assertEqual(names(tc.increased), ['ByteSwap', 'ArrayAppend'])
+ self.assertEqual(names(tc.decreased), ['BitCount'])
+ self.assertEqual(names(tc.added), ['TwoSum'])
+ self.assertEqual(names(tc.removed), ['AnyHashableWithAClass'])
# other way around
tc = TestComparator(self.new_results, self.old_results, 0.05)
- self.assertEquals(names(tc.unchanged), ['AngryPhonebook', 'Array2D'])
- self.assertEquals(names(tc.increased), ['BitCount'])
- self.assertEquals(names(tc.decreased), ['ByteSwap', 'ArrayAppend'])
- self.assertEquals(names(tc.added), ['AnyHashableWithAClass'])
- self.assertEquals(names(tc.removed), ['TwoSum'])
+ self.assertEqual(names(tc.unchanged), ['AngryPhonebook', 'Array2D'])
+ self.assertEqual(names(tc.increased), ['BitCount'])
+ self.assertEqual(names(tc.decreased), ['ByteSwap', 'ArrayAppend'])
+ self.assertEqual(names(tc.added), ['AnyHashableWithAClass'])
+ self.assertEqual(names(tc.removed), ['TwoSum'])
# delta_threshold determines the sorting into change groups;
# report only change above 100% (ByteSwap's runtime went to 0):
tc = TestComparator(self.old_results, self.new_results, 1)
- self.assertEquals(
+ self.assertEqual(
names(tc.unchanged),
['AngryPhonebook', 'Array2D', 'ArrayAppend', 'BitCount']
)
- self.assertEquals(names(tc.increased), ['ByteSwap'])
- self.assertEquals(tc.decreased, [])
+ self.assertEqual(names(tc.increased), ['ByteSwap'])
+ self.assertEqual(tc.decreased, [])
class TestReportFormatter(OldAndNewLog):
@@ -696,12 +696,12 @@
self.assert_report_contains(texts, self.html)
def test_values(self):
- self.assertEquals(
+ self.assertEqual(
ReportFormatter.values(PerformanceTestResult(
'1,AngryPhonebook,20,10664,12933,11035,576,10884'.split(','))),
('AngryPhonebook', '10664', '12933', '11035', '—')
)
- self.assertEquals(
+ self.assertEqual(
ReportFormatter.values(PerformanceTestResult(
'1,AngryPhonebook,1,12045,12045,12045,0,12045,10510336'
.split(','))),
@@ -712,16 +712,16 @@
'1,AngryPhonebook,1,12325,12325,12325,0,12325,10510336'.split(','))
r2 = PerformanceTestResult(
'1,AngryPhonebook,1,11616,11616,11616,0,11616,10502144'.split(','))
- self.assertEquals(
+ self.assertEqual(
ReportFormatter.values(ResultComparison(r1, r2)),
('AngryPhonebook', '12325', '11616', '-5.8%', '1.06x')
)
- self.assertEquals(
+ self.assertEqual(
ReportFormatter.values(ResultComparison(r2, r1)),
('AngryPhonebook', '11616', '12325', '+6.1%', '0.94x')
)
r2.max = r1.min + 1
- self.assertEquals(
+ self.assertEqual(
ReportFormatter.values(ResultComparison(r1, r2))[4],
'1.06x (?)' # is_dubious
)
@@ -742,12 +742,12 @@
PerformanceTestResults.
"""
performance_test_result = self.tc.added[0]
- self.assertEquals(
+ self.assertEqual(
ReportFormatter.header_for(performance_test_result),
('TEST', 'MIN', 'MAX', 'MEAN', 'MAX_RSS')
)
comparison_result = self.tc.increased[0]
- self.assertEquals(
+ self.assertEqual(
ReportFormatter.header_for(comparison_result),
('TEST', 'OLD', 'NEW', 'DELTA', 'RATIO')
)
@@ -859,17 +859,17 @@
self.assertIn('usage: compare_perf_tests.py', err.getvalue())
args = parse_args(self.required)
- self.assertEquals(args.old_file, 'old.log')
- self.assertEquals(args.new_file, 'new.log')
+ self.assertEqual(args.old_file, 'old.log')
+ self.assertEqual(args.new_file, 'new.log')
def test_format_argument(self):
- self.assertEquals(parse_args(self.required).format, 'markdown')
- self.assertEquals(
+ self.assertEqual(parse_args(self.required).format, 'markdown')
+ self.assertEqual(
parse_args(self.required + ['--format', 'markdown']).format,
'markdown')
- self.assertEquals(
+ self.assertEqual(
parse_args(self.required + ['--format', 'git']).format, 'git')
- self.assertEquals(
+ self.assertEqual(
parse_args(self.required + ['--format', 'html']).format, 'html')
with captured_output() as (_, err):
@@ -882,14 +882,14 @@
def test_delta_threshold_argument(self):
# default value
args = parse_args(self.required)
- self.assertEquals(args.delta_threshold, 0.05)
+ self.assertEqual(args.delta_threshold, 0.05)
# float parsing
args = parse_args(self.required + ['--delta-threshold', '0.1'])
- self.assertEquals(args.delta_threshold, 0.1)
+ self.assertEqual(args.delta_threshold, 0.1)
args = parse_args(self.required + ['--delta-threshold', '1'])
- self.assertEquals(args.delta_threshold, 1.0)
+ self.assertEqual(args.delta_threshold, 1.0)
args = parse_args(self.required + ['--delta-threshold', '.2'])
- self.assertEquals(args.delta_threshold, 0.2)
+ self.assertEqual(args.delta_threshold, 0.2)
with captured_output() as (_, err):
self.assertRaises(SystemExit, parse_args,
@@ -899,10 +899,10 @@
err.getvalue())
def test_output_argument(self):
- self.assertEquals(parse_args(self.required).output, None)
- self.assertEquals(parse_args(self.required +
- ['--output', 'report.log']).output,
- 'report.log')
+ self.assertEqual(parse_args(self.required).output, None)
+ self.assertEqual(parse_args(self.required +
+ ['--output', 'report.log']).output,
+ 'report.log')
def test_changes_only_argument(self):
self.assertFalse(parse_args(self.required).changes_only)
@@ -962,7 +962,7 @@
"""Writes Markdown formatted report to stdout and `--output` file."""
report_out, report_file = (
self.execute_main_with_format('markdown', test_output=True))
- self.assertEquals(report_out, report_file)
+ self.assertEqual(report_out, report_file)
self.assert_report_contains(self.markdown, report_file)
def test_git(self):
@@ -974,7 +974,7 @@
"""Writes Git formatted report to stdout and `--output` file."""
report_out, report_file = (
self.execute_main_with_format('git', test_output=True))
- self.assertEquals(report_out, report_file)
+ self.assertEqual(report_out, report_file)
self.assert_report_contains(self.git, report_file)
def test_html(self):
@@ -986,7 +986,7 @@
"""Writes HTML formatted report to stdout and `--output` file."""
report_out, report_file = (
self.execute_main_with_format('html', test_output=True))
- self.assertEquals(report_out, report_file)
+ self.assertEqual(report_out, report_file)
self.assert_report_contains(self.html, report_file)
diff --git a/benchmark/single-source/Codable.swift b/benchmark/single-source/Codable.swift
index b0c451a..1729a7a 100644
--- a/benchmark/single-source/Codable.swift
+++ b/benchmark/single-source/Codable.swift
@@ -107,17 +107,33 @@
JSONTester = CodablePerfTester(encoder: JSONEncoder(), decoder: JSONDecoder())
}
+#if !_runtime(_ObjC)
+// If we do not have an objc-runtime, then we do not have a definition for
+// autoreleasepool. Add in our own fake autoclosure for it that is inline
+// always. That should be able to be eaten through by the optimizer no problem.
+@inline(__always)
+public func autoreleasepool<Result>(
+ invoking body: () throws -> Result
+) rethrows -> Result {
+ return try body()
+}
+#endif
+
@inline(never)
public func run_JSONPerfEncode(_ N: Int) {
- for _ in 0 ..< N {
- JSONTester.encode()
+ autoreleasepool {
+ for _ in 0 ..< N {
+ JSONTester.encode()
+ }
}
}
@inline(never)
public func run_JSONPerfDecode(_ N: Int) {
- for _ in 0 ..< N {
- JSONTester.decode()
+ autoreleasepool {
+ for _ in 0 ..< N {
+ JSONTester.decode()
+ }
}
}
@@ -131,15 +147,19 @@
@inline(never)
public func run_PlistPerfEncode(_ N: Int) {
- for _ in 0 ..< N {
- plistTester.encode()
+ autoreleasepool {
+ for _ in 0 ..< N {
+ plistTester.encode()
+ }
}
}
@inline(never)
public func run_PlistPerfDecode(_ N: Int) {
- for _ in 0 ..< N {
- plistTester.decode()
+ autoreleasepool {
+ for _ in 0 ..< N {
+ plistTester.decode()
+ }
}
}
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 8e51106..f3e9d2b 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -755,9 +755,10 @@
endif()
endif()
- if (SWIFT_COMPILER_VERSION)
- if(${SWIFTLIB_SINGLE_SDK} IN_LIST SWIFT_APPLE_PLATFORMS)
- list(APPEND SWIFTLIB_SINGLE_LINK_FLAGS "-Xlinker" "-current_version" "-Xlinker" "${SWIFT_COMPILER_VERSION}" "-Xlinker" "-compatibility_version" "-Xlinker" "1")
+ if(${SWIFTLIB_SINGLE_SDK} IN_LIST SWIFT_APPLE_PLATFORMS)
+ list(APPEND SWIFTLIB_SINGLE_LINK_FLAGS "-Xlinker" "-compatibility_version" "-Xlinker" "1")
+ if (SWIFT_COMPILER_VERSION)
+ list(APPEND SWIFTLIB_SINGLE_LINK_FLAGS "-Xlinker" "-current_version" "-Xlinker" "${SWIFT_COMPILER_VERSION}" )
endif()
endif()
@@ -1848,12 +1849,6 @@
set(swiftlib_swift_compile_private_frameworks_flag "-Fsystem" "${SWIFT_SDK_${sdk}_ARCH_${arch}_PATH}/System/Library/PrivateFrameworks/")
endif()
- if("${sdk}" STREQUAL WINDOWS)
- if(arch STREQUAL x86_64)
- set(swiftlib_swift_compile_flags_arch -Xcc -D_AMD64_)
- endif()
- endif()
-
# Add this library variant.
_add_swift_library_single(
${VARIANT_NAME}
@@ -2200,83 +2195,6 @@
PROPERTIES FOLDER "Swift executables")
endfunction()
-# Add an executable for the host machine.
-#
-# Usage:
-# add_swift_executable(name
-# [DEPENDS dep1 ...]
-# [LLVM_COMPONENT_DEPENDS comp1 ...]
-# [FILE_DEPENDS target1 ...]
-# [LINK_LIBRARIES target1 ...]
-# [EXCLUDE_FROM_ALL]
-# [DONT_STRIP_NON_MAIN_SYMBOLS]
-# [DISABLE_ASLR]
-# source1 [source2 source3 ...])
-#
-# name
-# Name of the executable (e.g., swift).
-#
-# LIBRARIES
-# Libraries this executable depends on, without variant suffixes.
-#
-# LLVM_COMPONENT_DEPENDS
-# LLVM components this executable depends on.
-#
-# FILE_DEPENDS
-# Additional files this executable depends on.
-#
-# LINK_LIBRARIES
-# Libraries to link with.
-#
-# EXCLUDE_FROM_ALL
-# Whether to exclude this executable from the ALL_BUILD target.
-#
-# DONT_STRIP_NON_MAIN_SYMBOLS
-# Should we not strip non main symbols.
-#
-# DISABLE_ASLR
-# Should we compile with -Wl,-no_pie so that ASLR is disabled?
-#
-# source1 ...
-# Sources to add into this executable.
-#
-# Note:
-# Host executables are not given a variant suffix. To build an executable for
-# each SDK and ARCH variant, use add_swift_target_executable.
-function(add_swift_executable name)
- # Parse the arguments we were given.
- cmake_parse_arguments(SWIFTEXE
- "EXCLUDE_FROM_ALL;DONT_STRIP_NON_MAIN_SYMBOLS;DISABLE_ASLR"
- ""
- "DEPENDS;LLVM_COMPONENT_DEPENDS;LINK_LIBRARIES;COMPILE_FLAGS"
- ${ARGN})
-
- translate_flag(${SWIFTEXE_EXCLUDE_FROM_ALL}
- "EXCLUDE_FROM_ALL"
- SWIFTEXE_EXCLUDE_FROM_ALL_FLAG)
- translate_flag(${SWIFTEXE_DONT_STRIP_NON_MAIN_SYMBOLS}
- "DONT_STRIP_NON_MAIN_SYMBOLS"
- SWIFTEXE_DONT_STRIP_NON_MAIN_SYMBOLS_FLAG)
- translate_flag(${SWIFTEXE_DISABLE_ASLR}
- "DISABLE_ASLR"
- SWIFTEXE_DISABLE_ASLR_FLAG)
-
- set(SWIFTEXE_SOURCES ${SWIFTEXE_UNPARSED_ARGUMENTS})
-
- _add_swift_executable_single(
- ${name}
- ${SWIFTEXE_SOURCES}
- DEPENDS ${SWIFTEXE_DEPENDS}
- LLVM_COMPONENT_DEPENDS ${SWIFTEXE_LLVM_COMPONENT_DEPENDS}
- LINK_LIBRARIES ${SWIFTEXE_LINK_LIBRARIES}
- SDK ${SWIFT_HOST_VARIANT_SDK}
- ARCHITECTURE ${SWIFT_HOST_VARIANT_ARCH}
- COMPILE_FLAGS ${SWIFTEXE_COMPILE_FLAGS}
- ${SWIFTEXE_EXCLUDE_FROM_ALL_FLAG}
- ${SWIFTEXE_DONT_STRIP_NON_MAIN_SYMBOLS_FLAG}
- ${SWIFTEXE_DISABLE_ASLR_FLAG})
-endfunction()
-
macro(add_swift_tool_subdirectory name)
add_llvm_subdirectory(SWIFT TOOL ${name})
endmacro()
@@ -2300,7 +2218,9 @@
MESSAGE "Swift Component is required to add a host tool")
# Create the executable rule.
- add_swift_executable(${executable}
+ _add_swift_executable_single(${executable}
+ SDK ${SWIFT_HOST_VARIANT_SDK}
+ ARCHITECTURE ${SWIFT_HOST_VARIANT_ARCH}
${ASHT_UNPARSED_ARGUMENTS})
swift_install_in_component(${ASHT_SWIFT_COMPONENT}
diff --git a/cmake/modules/StandaloneOverlay.cmake b/cmake/modules/StandaloneOverlay.cmake
index 98f55ef..a4cd97e 100644
--- a/cmake/modules/StandaloneOverlay.cmake
+++ b/cmake/modules/StandaloneOverlay.cmake
@@ -19,6 +19,7 @@
set(SWIFT_DARWIN_DEPLOYMENT_VERSION_IOS "7.0" CACHE STRING "")
set(SWIFT_DARWIN_DEPLOYMENT_VERSION_TVOS "9.0" CACHE STRING "")
set(SWIFT_DARWIN_DEPLOYMENT_VERSION_WATCHOS "2.0" CACHE STRING "")
+set(SWIFT_ENABLE_PARSEABLE_MODULE_INTERFACES TRUE)
set(SWIFT_SOURCE_DIR "${SWIFT_SOURCE_ROOT}/src/swift" CACHE PATH "")
set(SWIFT_PATH_TO_LLVM_SOURCE "${SWIFT_SOURCE_ROOT}/src/llvm" CACHE PATH "")
@@ -61,6 +62,7 @@
# Some overlays include the runtime's headers,
# and some of those headers are generated at build time.
add_subdirectory("${SWIFT_SOURCE_DIR}/include" "swift/include")
+add_subdirectory("${SWIFT_SOURCE_DIR}/apinotes" "swift/apinotes")
# Without this line, installing components is broken. This needs refactoring.
swift_configure_components()
diff --git a/cmake/modules/SwiftComponents.cmake b/cmake/modules/SwiftComponents.cmake
index ada4a1a..725c685 100644
--- a/cmake/modules/SwiftComponents.cmake
+++ b/cmake/modules/SwiftComponents.cmake
@@ -67,10 +67,25 @@
set(_SWIFT_DEFINED_COMPONENTS
"autolink-driver;compiler;clang-builtin-headers;clang-resource-dir-symlink;clang-builtin-headers-in-clang-resource-dir;stdlib;stdlib-experimental;sdk-overlay;parser-lib;editor-integration;tools;testsuite-tools;toolchain-dev-tools;dev;license;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers")
+# The default install components include all of the defined components, except
+# for the following exceptions.
+set(_SWIFT_DEFAULT_COMPONENTS "${_SWIFT_DEFINED_COMPONENTS}")
+# 'dev' takes up a lot of disk space and isn't part of a normal toolchain.
+list(REMOVE_ITEM _SWIFT_DEFAULT_COMPONENTS "dev")
+# These clang header options conflict with 'clang-builtin-headers'.
+list(REMOVE_ITEM _SWIFT_DEFAULT_COMPONENTS "clang-resource-dir-symlink")
+list(REMOVE_ITEM _SWIFT_DEFAULT_COMPONENTS "clang-builtin-headers-in-clang-resource-dir")
+# The sourcekit install variants are currently mutually exclusive.
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ list(REMOVE_ITEM _SWIFT_DEFAULT_COMPONENTS "sourcekit-inproc")
+else()
+ list(REMOVE_ITEM _SWIFT_DEFAULT_COMPONENTS "sourcekit-xpc-service")
+endif()
+
macro(swift_configure_components)
# Set the SWIFT_INSTALL_COMPONENTS variable to the default value if it is not passed in via -D
- set(SWIFT_INSTALL_COMPONENTS "${_SWIFT_DEFINED_COMPONENTS}" CACHE STRING
- "A semicolon-separated list of components to install ${_SWIFT_DEFINED_COMPONENTS}")
+ set(SWIFT_INSTALL_COMPONENTS "${_SWIFT_DEFAULT_COMPONENTS}" CACHE STRING
+ "A semicolon-separated list of components to install from the set ${_SWIFT_DEFINED_COMPONENTS}")
foreach(component ${_SWIFT_DEFINED_COMPONENTS})
string(TOUPPER "${component}" var_name_piece)
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 34bef31..86870dd 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _ABI:
.. highlight:: none
diff --git a/docs/ABI/TypeLayout.rst b/docs/ABI/TypeLayout.rst
index 7f5569c..4d6feb3 100644
--- a/docs/ABI/TypeLayout.rst
+++ b/docs/ABI/TypeLayout.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _ABI:
.. highlight:: none
diff --git a/docs/ABI/TypeMetadata.rst b/docs/ABI/TypeMetadata.rst
index 4091108..350945a 100644
--- a/docs/ABI/TypeMetadata.rst
+++ b/docs/ABI/TypeMetadata.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _ABI:
.. highlight:: none
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index 75fc706..a0f36cb 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -24,112 +24,6 @@
message(WARNING "Unable to find sphinx-build program. Not building docs")
endif()
-## Example testing
-
-find_program(LITRE_EXECUTABLE
- NAMES litre
- DOC "LitRe literate programming tool for docutils")
-
-find_program(SPHINX_EXECUTABLE
- NAMES sphinx-build
- HINTS $ENV{SPHINX_DIR}
- PATH_SUFFIXES bin
- DOC "Sphinx documentation generator")
-
-if(LITRE_EXECUTABLE)
- # Find all the .rst files
- file(GLOB_RECURSE rst_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.rst)
- set(subdir_CMakeLists)
-
- foreach(rst ${rst_files})
- # Prepare a testing directory containing a CMakeLists.txt
- # and example files extracted from the .rst
- set(test_dir "litre-tests/${rst}.litre-tests")
-
- add_custom_command(
- OUTPUT
- ${test_dir}/CMakeLists.txt
- COMMAND
- ${LITRE_EXECUTABLE}
- --default_compiler=${CMAKE_BINARY_DIR}/bin/swift
- "--dump_dir=${test_dir}"
- --traceback
- --report=severe # suppress most .rst errors. We have lots of them.
- ${CMAKE_CURRENT_SOURCE_DIR}/${rst}
- DEPENDS
- ${CMAKE_CURRENT_SOURCE_DIR}/${rst}
- COMMENT
- "Generating/Updating LitRe tests for ${rst}"
- VERBATIM
- )
-
- list(APPEND subdir_CMakeLists ${test_dir}/CMakeLists.txt)
- endforeach()
-
- # Create a top-level CMakeLists.txt in a temporary file
- add_custom_command(
- OUTPUT
- litre-top-CMakeLists.cmake
- COMMAND
- ${CMAKE_COMMAND} -DOUTPUT=litre-top-CMakeLists.cmake
- -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/GenerateTopLevelLitreCMakeLists.cmake
- ${rst_files}
- DEPENDS
- ${rst_files}
- COMMENT
- "Generating top-level LitRe CMakeLists.txt content"
- VERBATIM
- )
-
- # Only update the real top-level CMakeLists.txt if something changed
- add_custom_command(
- OUTPUT
- "litre-tests/CMakeLists.txt"
- COMMAND
- "${CMAKE_COMMAND}" "-E" "copy_if_different"
- "litre-top-CMakeLists.cmake" "litre-tests/CMakeLists.txt"
- DEPENDS
- "litre-top-CMakeLists.cmake"
- COMMENT
- "Updating top-level LitRe CMakeLists.txt"
- VERBATIM)
-
- # Create a build directory
- add_custom_command(
- OUTPUT "litre-tests/build"
- COMMAND "${CMAKE_COMMAND}" "-E" "make_directory" "litre-tests/build")
-
- # Run CMake itself to configure/build the tests
- add_custom_command(
- OUTPUT
- litre-tests/results
- COMMAND
- ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" "${CMAKE_CURRENT_BINARY_DIR}/litre-tests"
- COMMAND
- ${CMAKE_COMMAND} --build .
- COMMAND
- ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/litre-tests/results"
- WORKING_DIRECTORY
- litre-tests/build
- DEPENDS
- ${CMAKE_BINARY_DIR}/bin/swift
- litre-tests/CMakeLists.txt litre-tests/build ${subdir_CMakeLists}
- COMMENT
- "Running LitRe tests"
- VERBATIM
- )
-
- # Add a target so these tests show up in the Xcode project.
- add_custom_target(
- LiterateTests SOURCES ${rst_files}
- DEPENDS litre-tests/results
- )
- set_target_properties(LiterateTests PROPERTIES FOLDER "Tests")
-else()
- message(WARNING "LitRe not found; code examples won't be tested.")
-endif()
-
if (LLVM_ENABLE_DOXYGEN)
if (DOXYGEN_FOUND)
set(abs_srcdir ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md
index 1963b1e..e95bc56 100644
--- a/docs/ContinuousIntegration.md
+++ b/docs/ContinuousIntegration.md
@@ -10,6 +10,7 @@
- [Validation Testing](#validation-testing)
- [Linting](#linting)
- [Source Compatibility Testing](#source-compatibility-testing)
+ - [Sourcekit Stress Testing](#sourcekit-stress-testing)
- [Specific Preset Testing](#specific-preset-testing)
- [Build Swift Toolchain](#build-swift-toolchain)
- [Testing Compiler Performance](#testing-compiler-performance)
@@ -139,6 +140,12 @@
macOS platform | @swift-ci Please Test Source Compatibility Release | Swift Source Compatibility Suite on macOS Platform (Release)
macOS platform | @swift-ci Please Test Source Compatibility Debug | Swift Source Compatibility Suite on macOS Platform (Debug)
+### Sourcekit Stress Testing
+
+Platform | Comment | Check Status
+------------ | ------- | ------------
+macOS platform | @swift-ci Please Sourcekit Stress test | Swift Sourcekit Stress Tester on macOS Platform
+
### Specific Preset Testing
Platform | Comment | Check Status
diff --git a/docs/DependencyAnalysis.rst b/docs/DependencyAnalysis.rst
index 91a1a97..e7a1a36 100644
--- a/docs/DependencyAnalysis.rst
+++ b/docs/DependencyAnalysis.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
===================
Dependency Analysis
===================
diff --git a/docs/GenerateTopLevelLitreCMakeLists.cmake b/docs/GenerateTopLevelLitreCMakeLists.cmake
deleted file mode 100644
index 16fa3af..0000000
--- a/docs/GenerateTopLevelLitreCMakeLists.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-set(rst_files)
-foreach(i RANGE 5 ${CMAKE_ARGC})
- list(APPEND rst_files ${CMAKE_ARGV${i}})
-endforeach()
-configure_file(${SOURCE_DIR}/LitReTemplate.cmake ${OUTPUT} @ONLY)
diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst
index b15fab8..8d0a76c 100644
--- a/docs/Lexicon.rst
+++ b/docs/Lexicon.rst
@@ -3,8 +3,6 @@
.. title:: Lexicon
.. default-role:: term
-.. @raise litre.TestsAreMissing
-
This file defines several terms used by the Swift compiler and standard library
source code, tests, and commit messages. See also the `LLVM lexicon`_.
diff --git a/docs/Literals.rst b/docs/Literals.rst
index c7fde55..f6d4396 100644
--- a/docs/Literals.rst
+++ b/docs/Literals.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
Literals
========
diff --git a/docs/LitreTemplate.cmake b/docs/LitreTemplate.cmake
deleted file mode 100644
index 3bfbb7165..0000000
--- a/docs/LitreTemplate.cmake
+++ /dev/null
@@ -1,18 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-find_program(LITRE_EXECUTABLE
- NAMES litre
- DOC "LitRe literate programming tool for docutils")
-
-# Make the LitreTesting cmake module available
-execute_process(
- COMMAND ${LITRE_EXECUTABLE} --cmake_module_path
- OUTPUT_VARIABLE litre_cmake_module_path
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
-list(APPEND CMAKE_MODULE_PATH ${litre_cmake_module_path})
-set(rst_files "@rst_files@")
-foreach(rst ${rst_files})
- add_subdirectory("${rst}.litre-tests")
-endforeach()
diff --git a/docs/LogicalObjects.rst b/docs/LogicalObjects.rst
index a5fef5d..6e32da0 100644
--- a/docs/LogicalObjects.rst
+++ b/docs/LogicalObjects.rst
@@ -1,5 +1,3 @@
-.. @raise litre.TestsAreMissing
-
Logical Objects
===============
diff --git a/docs/Modules.rst b/docs/Modules.rst
index 16dfc4f..fbea23d 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. default-role:: term
.. title:: Modules User Model
diff --git a/docs/OptimizationTips.rst b/docs/OptimizationTips.rst
index 9a6312c..f00de1f 100644
--- a/docs/OptimizationTips.rst
+++ b/docs/OptimizationTips.rst
@@ -161,7 +161,7 @@
func usingE(_ e: E) {
e.doSomething() // There is no sub class in the file that declares this class.
// The compiler can remove virtual calls to doSomething()
- // and directly call A's doSomething method.
+ // and directly call E's doSomething method.
}
func usingF(_ f: F) -> Int {
diff --git a/docs/PatternMatching.rst b/docs/PatternMatching.rst
index f26d7e8..0968bfa 100644
--- a/docs/PatternMatching.rst
+++ b/docs/PatternMatching.rst
@@ -1,4 +1,3 @@
-.. @raise litre.TestsAreMissing
.. _PatternMatching:
Pattern Matching
diff --git a/docs/SIL.rst b/docs/SIL.rst
index 699e9f3..1e5b781 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -1,4 +1,3 @@
-.. @raise litre.TestsAreMissing
.. highlight:: none
Swift Intermediate Language (SIL)
@@ -2828,6 +2827,13 @@
``$Optional<T>``, except that it is ``null`` if the heap object has begun
deallocation.
+If ``[take]`` is specified then the underlying weak reference is invalidated
+implying that the weak reference count of the loaded value is decremented. If
+``[take]`` is not specified then the underlying weak reference count is not
+affected by this operation (i.e. it is a +0 weak ref count operation). In either
+case, the strong reference count will be incremented before any changes to the
+weak reference count.
+
This operation must be atomic with respect to the final ``strong_release`` on
the operand heap object. It need not be atomic with respect to ``store_weak``
operations on the same address.
@@ -2846,7 +2852,13 @@
If ``[initialization]`` is given, the weak reference must currently either be
uninitialized or destroyed. If it is not given, the weak reference must
-currently be initialized.
+currently be initialized. After the evaluation:
+
+* The value that was originally referenced by the weak reference will have
+ its weak reference count decremented by 1.
+* If the optionally typed operand is non-nil, the strong reference wrapped in
+ the optional has its weak reference count incremented by 1. In contrast, the reference's
+ strong reference count is not touched.
This operation must be atomic with respect to the final ``strong_release`` on
the operand (source) heap object. It need not be atomic with respect to
@@ -3348,11 +3360,12 @@
`````````````
::
- sil-instruction ::= 'partial_apply' callee-ownership-attr? sil-value
+ sil-instruction ::= 'partial_apply' callee-ownership-attr? on-stack-attr? sil-value
sil-apply-substitution-list?
'(' (sil-value (',' sil-value)*)? ')'
':' sil-type
callee-ownership-attr ::= '[callee_guaranteed]'
+ on-stack-attr ::= '[on_stack]'
%c = partial_apply %0(%1, %2, ...) : $(Z..., A, B, ...) -> R
// Note that the type of the callee '%0' is specified *after* the arguments
@@ -3370,12 +3383,18 @@
Creates a closure by partially applying the function ``%0`` to a partial
sequence of its arguments. In the instruction syntax, the type of the callee is
specified after the argument list; the types of the argument and of the defined
-value are derived from the function type of the callee. The closure context will
-be allocated with retain count 1 and initialized to contain the values ``%1``,
+value are derived from the function type of the callee. If the ``partial_apply``
+has an escaping function type (not ``[on_stack]``) the closure context will be
+allocated with retain count 1 and initialized to contain the values ``%1``,
``%2``, etc. The closed-over values will not be retained; that must be done
-separately before the ``partial_apply``. The closure does however take
-ownership of the partially applied arguments; when the closure reference
-count reaches zero, the contained values will be destroyed.
+separately before the ``partial_apply``. The closure does however take ownership
+of the partially applied arguments; when the closure reference count reaches
+zero, the contained values will be destroyed. If the ``partial_apply`` has a
+``@noescape`` function type (``partial_apply [on_stack]``) the closure context
+is allocated on the stack and intialized to contain the closed-over values. The
+closed-over values are not retained, lifetime of the closed-over values must be
+managed separately. The lifetime of the stack context of a ``partial_apply
+[stack]`` must be terminated with a ``dealloc_stack``.
If the callee is generic, all of its generic parameters must be bound by the
given substitution list. The arguments are given with these generic
diff --git a/docs/SequencesAndCollections.rst b/docs/SequencesAndCollections.rst
index e0010c9..2eef944 100644
--- a/docs/SequencesAndCollections.rst
+++ b/docs/SequencesAndCollections.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. default-role:: code
====================================
diff --git a/docs/StdlibRationales.rst b/docs/StdlibRationales.rst
index 097dc8a..3b8503b 100644
--- a/docs/StdlibRationales.rst
+++ b/docs/StdlibRationales.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
=================================================
Rationales for the Swift standard library designs
=================================================
diff --git a/docs/StoredAndComputedVariables.rst b/docs/StoredAndComputedVariables.rst
index 3d8c196..22dd625 100644
--- a/docs/StoredAndComputedVariables.rst
+++ b/docs/StoredAndComputedVariables.rst
@@ -1,5 +1,3 @@
-.. @raise litre.TestsAreMissing
-
=============================
Stored and Computed Variables
=============================
diff --git a/docs/StringDesign.rst b/docs/StringDesign.rst
index d8973bc..26c0c8f 100644
--- a/docs/StringDesign.rst
+++ b/docs/StringDesign.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
.. raw:: html
<style>
diff --git a/docs/TypeChecker.rst b/docs/TypeChecker.rst
index 6aece99..d383781 100644
--- a/docs/TypeChecker.rst
+++ b/docs/TypeChecker.rst
@@ -1,5 +1,3 @@
-.. @raise litre.TestsAreMissing
-
Type Checker Design and Implementation
========================================
diff --git a/docs/WindowsBuild.md b/docs/WindowsBuild.md
index 4673177..ecdd101 100644
--- a/docs/WindowsBuild.md
+++ b/docs/WindowsBuild.md
@@ -103,7 +103,7 @@
cmake -G Ninja^
-DCMAKE_BUILD_TYPE=Debug^
-DCMAKE_C_COMPILER=cl^
- -DCMAKE_CXX_COMPIELR=cl^
+ -DCMAKE_CXX_COMPILER=cl^
S:\cmark
popd
cmake --build "S:\build\Ninja-DebugAssert\cmark-windows-amd64"
@@ -133,7 +133,7 @@
- Update your path to include the LLVM tools.
```cmd
-set PATH=%PATH%;S:\build\Ninja-DebugAssert\llvm-windows-amd64\bin
+set PATH=S:\build\Ninja-DebugAssert\llvm-windows-amd64\bin;%PATH%
```
### 7. Build Swift
diff --git a/docs/archive/LangRefNew.rst b/docs/archive/LangRefNew.rst
index d14ec79..131d3ce 100644
--- a/docs/archive/LangRefNew.rst
+++ b/docs/archive/LangRefNew.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
===============================
Swift Language Reference Manual
===============================
diff --git a/docs/archive/NamespaceLevelVarsAndTopLevelCode.rst b/docs/archive/NamespaceLevelVarsAndTopLevelCode.rst
index 5e9fe71..18aad26 100644
--- a/docs/archive/NamespaceLevelVarsAndTopLevelCode.rst
+++ b/docs/archive/NamespaceLevelVarsAndTopLevelCode.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
.. warning:: This document was used in planning Swift 1.0; it has not been kept
up to date and does not describe the current or planned behavior of Swift.
diff --git a/docs/archive/Objective-CInteroperability.rst b/docs/archive/Objective-CInteroperability.rst
index 2ad9689..4e121be 100644
--- a/docs/archive/Objective-CInteroperability.rst
+++ b/docs/archive/Objective-CInteroperability.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
============================
Objective-C Interoperability
============================
diff --git a/docs/archive/Resilience.rst b/docs/archive/Resilience.rst
index a65079f..64b32f8 100644
--- a/docs/archive/Resilience.rst
+++ b/docs/archive/Resilience.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _Resilience:
Resilience
diff --git a/docs/contents.rst b/docs/contents.rst
index 8d2e9ee..1a57554 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -1,4 +1,3 @@
-.. @raise litre.TestsAreMissing
.. _contents:
Contents
diff --git a/docs/proposals/Concurrency.rst b/docs/proposals/Concurrency.rst
index 0e34b05..dfff719 100644
--- a/docs/proposals/Concurrency.rst
+++ b/docs/proposals/Concurrency.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. ConcurrencyModel:
*Note*: This document is **not an accepted Swift proposal**. It does not describe Swift's concurrency mechanisms as they currently exist, nor is it a roadmap for the addition of concurrency mechanisms in future versions of Swift.
diff --git a/docs/proposals/DeclarationTypeChecker.rst b/docs/proposals/DeclarationTypeChecker.rst
index 5d3d395..711c0f6 100644
--- a/docs/proposals/DeclarationTypeChecker.rst
+++ b/docs/proposals/DeclarationTypeChecker.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
Declaration Type Checker
========================
diff --git a/docs/proposals/Inplace.rst b/docs/proposals/Inplace.rst
index c571b73..f14e0d1 100644
--- a/docs/proposals/Inplace.rst
+++ b/docs/proposals/Inplace.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
=====================
In-Place Operations
=====================
diff --git a/docs/proposals/TypeState.rst b/docs/proposals/TypeState.rst
index a09700d..e4b94d9 100644
--- a/docs/proposals/TypeState.rst
+++ b/docs/proposals/TypeState.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
General Type State Notes
========================
diff --git a/docs/proposals/ValueSemantics.rst b/docs/proposals/ValueSemantics.rst
index 72d514f..04ce7fc 100644
--- a/docs/proposals/ValueSemantics.rst
+++ b/docs/proposals/ValueSemantics.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _ValueSemantics:
==========================
diff --git a/docs/proposals/archive/MemoryAndConcurrencyModel.rst b/docs/proposals/archive/MemoryAndConcurrencyModel.rst
index 3f1fcff..6e35b3f 100644
--- a/docs/proposals/archive/MemoryAndConcurrencyModel.rst
+++ b/docs/proposals/archive/MemoryAndConcurrencyModel.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _MemoryAndConcurrencyModel:
Swift Memory and Concurrency Model
diff --git a/docs/proposals/archive/ProgramStructureAndCompilationModel.rst b/docs/proposals/archive/ProgramStructureAndCompilationModel.rst
index e6219ea..49d6cd9 100644
--- a/docs/proposals/archive/ProgramStructureAndCompilationModel.rst
+++ b/docs/proposals/archive/ProgramStructureAndCompilationModel.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _ProgramStructureAndCompilationModel:
.. highlight:: none
diff --git a/docs/proposals/rejected/Clonable.rst b/docs/proposals/rejected/Clonable.rst
index 2dfaf9e..b67b05b 100644
--- a/docs/proposals/rejected/Clonable.rst
+++ b/docs/proposals/rejected/Clonable.rst
@@ -1,7 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
-
==========
Clonable
==========
diff --git a/docs/proposals/valref.rst b/docs/proposals/valref.rst
index b373097..c1d8623 100644
--- a/docs/proposals/valref.rst
+++ b/docs/proposals/valref.rst
@@ -1,6 +1,5 @@
:orphan:
-.. @raise litre.TestsAreMissing
.. _valref:
=======================
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index fee647c..52795bb 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -493,7 +493,7 @@
HasLazyConformances : 1
);
- SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+2+8+16,
+ SWIFT_INLINE_BITFIELD_FULL(ProtocolDecl, NominalTypeDecl, 1+1+1+1+1+1+1+2+1+8+16,
/// Whether the \c RequiresClass bit is valid.
RequiresClassValid : 1,
@@ -519,6 +519,9 @@
/// The stage of the circularity check for this protocol.
Circularity : 2,
+ /// Whether we've computed the inherited protocols list yet.
+ InheritedProtocolsValid : 1,
+
: NumPadBits,
/// If this is a compiler-known protocol, this will be a KnownProtocolKind
@@ -3562,11 +3565,16 @@
void createObjCMethodLookup();
struct {
+ /// The superclass decl and a bit to indicate whether the
+ /// superclass was computed yet or not.
+ llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;
+
/// The superclass type and a bit to indicate whether the
/// superclass was computed yet or not.
- llvm::PointerIntPair<Type, 1, bool> Superclass;
+ llvm::PointerIntPair<Type, 1, bool> SuperclassType;
} LazySemanticInfo;
+ friend class SuperclassDeclRequest;
friend class SuperclassTypeRequest;
friend class TypeChecker;
@@ -3888,6 +3896,18 @@
class ProtocolDecl final : public NominalTypeDecl {
SourceLoc ProtocolLoc;
+ ArrayRef<ProtocolDecl *> InheritedProtocols;
+
+ struct {
+ /// The superclass decl and a bit to indicate whether the
+ /// superclass was computed yet or not.
+ llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;
+
+ /// The superclass type and a bit to indicate whether the
+ /// superclass was computed yet or not.
+ llvm::PointerIntPair<Type, 1, bool> SuperclassType;
+ } LazySemanticInfo;
+
/// The generic signature representing exactly the new requirements introduced
/// by this protocol.
const Requirement *RequirementSignature = nullptr;
@@ -3898,12 +3918,9 @@
bool existentialTypeSupportedSlow(LazyResolver *resolver);
- struct {
- /// The superclass type and a bit to indicate whether the
- /// superclass was computed yet or not.
- llvm::PointerIntPair<Type, 1, bool> Superclass;
- } LazySemanticInfo;
+ ArrayRef<ProtocolDecl *> getInheritedProtocolsSlow();
+ friend class SuperclassDeclRequest;
friend class SuperclassTypeRequest;
friend class TypeChecker;
@@ -3915,7 +3932,12 @@
using Decl::getASTContext;
/// Retrieve the set of protocols inherited from this protocol.
- llvm::TinyPtrVector<ProtocolDecl *> getInheritedProtocols() const;
+ ArrayRef<ProtocolDecl *> getInheritedProtocols() const {
+ if (Bits.ProtocolDecl.InheritedProtocolsValid)
+ return InheritedProtocols;
+
+ return const_cast<ProtocolDecl *>(this)->getInheritedProtocolsSlow();
+ }
/// Determine whether this protocol has a superclass.
bool hasSuperclass() const { return (bool)getSuperclassDecl(); }
@@ -5875,7 +5897,7 @@
/// enum. EnumElementDecls are represented in the AST as members of their
/// parent EnumDecl, although syntactically they are subordinate to the
/// EnumCaseDecl.
-class EnumElementDecl : public ValueDecl {
+class EnumElementDecl : public DeclContext, public ValueDecl {
/// This is the type specified with the enum element, for
/// example 'Int' in 'case Y(Int)'. This is null if there is no type
/// associated with this element, as in 'case Z' or in all elements of enum
@@ -5895,7 +5917,8 @@
SourceLoc EqualsLoc,
LiteralExpr *RawValueExpr,
DeclContext *DC)
- : ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
+ : DeclContext(DeclContextKind::EnumElementDecl, DC),
+ ValueDecl(DeclKind::EnumElement, DC, Name, IdentifierLoc),
Params(Params),
EqualsLoc(EqualsLoc),
RawValueExpr(RawValueExpr)
@@ -5963,14 +5986,23 @@
return getParameterList() != nullptr;
}
- static bool classof(const Decl *D) {
- return D->getKind() == DeclKind::EnumElement;
- }
-
/// True if the case is marked 'indirect'.
bool isIndirect() const {
return getAttrs().hasAttribute<IndirectAttr>();
}
+
+ static bool classof(const Decl *D) {
+ return D->getKind() == DeclKind::EnumElement;
+ }
+
+ static bool classof(const DeclContext *DC) {
+ if (auto D = DC->getAsDecl())
+ return classof(D);
+ return false;
+ }
+
+ using DeclContext::operator new;
+ using Decl::getASTContext;
};
inline SourceRange EnumCaseDecl::getSourceRange() const {
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index 14497b9..ddfbbb9 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -78,6 +78,7 @@
Initializer,
TopLevelCodeDecl,
SubscriptDecl,
+ EnumElementDecl,
AbstractFunctionDecl,
SerializedLocal,
Last_LocalDeclContextKind = SerializedLocal,
@@ -230,6 +231,7 @@
case DeclContextKind::TopLevelCodeDecl:
case DeclContextKind::AbstractFunctionDecl:
case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::EnumElementDecl:
case DeclContextKind::GenericTypeDecl:
case DeclContextKind::ExtensionDecl:
return ASTHierarchy::Decl;
diff --git a/include/swift/AST/DeclNodes.def b/include/swift/AST/DeclNodes.def
index eca225a..5aeef91 100644
--- a/include/swift/AST/DeclNodes.def
+++ b/include/swift/AST/DeclNodes.def
@@ -171,7 +171,7 @@
ABSTRACT_FUNCTION_DECL(Func, AbstractFunctionDecl)
ABSTRACT_FUNCTION_DECL(Accessor, FuncDecl)
DECL_RANGE(AbstractFunction, Constructor, Accessor)
- VALUE_DECL(EnumElement, ValueDecl)
+ CONTEXT_VALUE_DECL(EnumElement, ValueDecl)
DECL_RANGE(Value, Enum, EnumElement)
ITERABLE_GENERIC_DECL(Extension, Decl)
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index f9c4321..96fe433 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -3172,6 +3172,12 @@
ERROR(continue_not_in_this_stmt,none,
"'continue' cannot be used with %0 statements", (StringRef))
+ERROR(unresolved_label,none,
+ "use of unresolved label %0", (Identifier))
+ERROR(unresolved_label_corrected,none,
+ "use of unresolved label %0; did you mean %1?",
+ (Identifier, Identifier))
+
// Switch Stmt
ERROR(no_match_operator,none,
"no binary '~=' operator available for 'switch' statement", ())
diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h
index 7f73230..5f7177a 100644
--- a/include/swift/AST/NameLookupRequests.h
+++ b/include/swift/AST/NameLookupRequests.h
@@ -133,7 +133,7 @@
/// Request the superclass declaration for the given class.
class SuperclassDeclRequest :
public SimpleRequest<SuperclassDeclRequest,
- CacheKind::Uncached, // FIXME: Cache these
+ CacheKind::SeparatelyCached,
ClassDecl *,
NominalTypeDecl *> {
public:
@@ -149,6 +149,8 @@
public:
// Caching
bool isCached() const { return true; }
+ Optional<ClassDecl *> getCachedResult() const;
+ void cacheResult(ClassDecl *value) const;
// Cycle handling
void diagnoseCycle(DiagnosticEngine &diags) const;
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 0e4e5e6..b0565c7 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -3208,6 +3208,8 @@
return cast<GenericFunctionType>(fnType->getCanonicalType());
}
+ CanFunctionType substGenericArgs(SubstitutionMap subs) const;
+
CanGenericSignature getGenericSignature() const {
return CanGenericSignature(getPointer()->getGenericSignature());
}
diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h
index ccabc6f..d84f82c 100644
--- a/include/swift/Frontend/Frontend.h
+++ b/include/swift/Frontend/Frontend.h
@@ -614,8 +614,7 @@
private:
void createREPLFile(const ImplicitImports &implicitImports);
- std::unique_ptr<DelayedParsingCallbacks>
- computeDelayedParsingCallback(bool isPrimary);
+ std::unique_ptr<DelayedParsingCallbacks> computeDelayedParsingCallback();
void addMainFileToModule(const ImplicitImports &implicitImports);
@@ -626,15 +625,13 @@
void parseLibraryFile(unsigned BufferID,
const ImplicitImports &implicitImports,
PersistentParserState &PersistentState,
- DelayedParsingCallbacks *PrimaryDelayedCB,
- DelayedParsingCallbacks *SecondaryDelayedCB);
+ DelayedParsingCallbacks *DelayedCB);
/// Return true if had load error
bool
parsePartialModulesAndLibraryFiles(const ImplicitImports &implicitImports,
PersistentParserState &PersistentState,
- DelayedParsingCallbacks *PrimaryDelayedCB,
- DelayedParsingCallbacks *SecondaryDelayedCB);
+ DelayedParsingCallbacks *DelayedCB);
OptionSet<TypeCheckingFlags> computeTypeCheckingOptions();
diff --git a/include/swift/Parse/DelayedParsingCallbacks.h b/include/swift/Parse/DelayedParsingCallbacks.h
index b8dfc04..7359dcb 100644
--- a/include/swift/Parse/DelayedParsingCallbacks.h
+++ b/include/swift/Parse/DelayedParsingCallbacks.h
@@ -35,15 +35,6 @@
SourceRange BodyRange) = 0;
};
-class AlwaysDelayedCallbacks : public DelayedParsingCallbacks {
- bool shouldDelayFunctionBodyParsing(Parser &TheParser,
- AbstractFunctionDecl *AFD,
- const DeclAttributes &Attrs,
- SourceRange BodyRange) override {
- return true;
- }
-};
-
/// Implementation of callbacks that guide the parser in delayed
/// parsing for code completion.
class CodeCompleteDelayedCallbacks : public DelayedParsingCallbacks {
diff --git a/include/swift/Parse/Lexer.h b/include/swift/Parse/Lexer.h
index 5cf9b20..cbe82c8 100644
--- a/include/swift/Parse/Lexer.h
+++ b/include/swift/Parse/Lexer.h
@@ -22,8 +22,7 @@
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/LexerState.h"
#include "swift/Parse/Token.h"
-#include "swift/Syntax/References.h"
-#include "swift/Syntax/Trivia.h"
+#include "swift/Parse/ParsedTrivia.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/SaveAndRestore.h"
@@ -118,13 +117,13 @@
///
/// This is only preserved if this Lexer was constructed with
/// `TriviaRetentionMode::WithTrivia`.
- syntax::Trivia LeadingTrivia;
+ ParsedTrivia LeadingTrivia;
/// The current trailing trivia for the next token.
///
/// This is only preserved if this Lexer was constructed with
/// `TriviaRetentionMode::WithTrivia`.
- syntax::Trivia TrailingTrivia;
+ ParsedTrivia TrailingTrivia;
Lexer(const Lexer&) = delete;
void operator=(const Lexer&) = delete;
@@ -185,8 +184,8 @@
/// Lex a token. If \c TriviaRetentionMode is \c WithTrivia, passed pointers
/// to trivias are populated.
- void lex(Token &Result, syntax::Trivia &LeadingTriviaResult,
- syntax::Trivia &TrailingTriviaResult) {
+ void lex(Token &Result, ParsedTrivia &LeadingTriviaResult,
+ ParsedTrivia &TrailingTriviaResult) {
Result = NextToken;
if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
LeadingTriviaResult = {LeadingTrivia};
@@ -197,7 +196,7 @@
}
void lex(Token &Result) {
- syntax::Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
lex(Result, LeadingTrivia, TrailingTrivia);
}
@@ -229,7 +228,7 @@
/// After restoring the state, lexer will return this token and continue from
/// there.
State getStateForBeginningOfToken(const Token &Tok,
- const syntax::Trivia &LeadingTrivia = {}) const {
+ const ParsedTrivia &LeadingTrivia = {}) const {
// If the token has a comment attached to it, rewind to before the comment,
// not just the start of the token. This ensures that we will re-lex and
@@ -529,7 +528,7 @@
void lexOperatorIdentifier();
void lexHexNumber();
void lexNumber();
- void lexTrivia(syntax::Trivia &T, bool IsForTrailingTrivia);
+ void lexTrivia(ParsedTrivia &T, bool IsForTrailingTrivia);
static unsigned lexUnicodeEscape(const char *&CurPtr, Lexer *Diags);
unsigned lexCharacter(const char *&CurPtr, char StopQuote,
diff --git a/include/swift/Parse/LexerState.h b/include/swift/Parse/LexerState.h
index 5ce65d3..f400cfe 100644
--- a/include/swift/Parse/LexerState.h
+++ b/include/swift/Parse/LexerState.h
@@ -19,7 +19,7 @@
#include "llvm/ADT/Optional.h"
#include "swift/Basic/SourceLoc.h"
-#include "swift/Syntax/Trivia.h"
+#include "swift/Parse/ParsedTrivia.h"
namespace swift {
class Lexer;
@@ -39,7 +39,7 @@
private:
explicit LexerState(SourceLoc Loc) : Loc(Loc) {}
SourceLoc Loc;
- llvm::Optional<syntax::Trivia> LeadingTrivia;
+ llvm::Optional<ParsedTrivia> LeadingTrivia;
friend class Lexer;
};
diff --git a/include/swift/Parse/ParsedRawSyntaxNode.h b/include/swift/Parse/ParsedRawSyntaxNode.h
index e415789..a43639c 100644
--- a/include/swift/Parse/ParsedRawSyntaxNode.h
+++ b/include/swift/Parse/ParsedRawSyntaxNode.h
@@ -14,14 +14,15 @@
#define SWIFT_PARSE_PARSEDRAWSYNTAXNODE_H
#include "swift/Basic/SourceLoc.h"
+#include "swift/Parse/ParsedTrivia.h"
#include "swift/Parse/Token.h"
#include "swift/Syntax/SyntaxKind.h"
-#include "swift/Syntax/Trivia.h"
#include <vector>
namespace swift {
typedef void *OpaqueSyntaxNode;
+class SyntaxParsingContext;
/// Represents a raw syntax node formed by the parser.
///
@@ -50,12 +51,14 @@
CharSourceRange Range;
};
struct DeferredLayoutNode {
- std::vector<ParsedRawSyntaxNode> Children;
+ ArrayRef<ParsedRawSyntaxNode> Children;
};
struct DeferredTokenNode {
- Token Tok;
- syntax::Trivia LeadingTrivia;
- syntax::Trivia TrailingTrivia;
+ const ParsedTriviaPiece *TriviaPieces;
+ SourceLoc TokLoc;
+ unsigned TokLength;
+ uint16_t NumLeadingTrivia;
+ uint16_t NumTrailingTrivia;
};
union {
@@ -77,16 +80,22 @@
assert(getKind() == k && "Syntax kind with too large value!");
}
- ParsedRawSyntaxNode(Token tok,
- syntax::Trivia leadingTrivia,
- syntax::Trivia trailingTrivia)
- : DeferredToken{std::move(tok),
- std::move(leadingTrivia),
- std::move(trailingTrivia)},
+ ParsedRawSyntaxNode(tok tokKind, SourceLoc tokLoc, unsigned tokLength,
+ const ParsedTriviaPiece *triviaPieces,
+ unsigned numLeadingTrivia,
+ unsigned numTrailingTrivia)
+ : DeferredToken{triviaPieces,
+ tokLoc, tokLength,
+ uint16_t(numLeadingTrivia),
+ uint16_t(numTrailingTrivia)},
SynKind(uint16_t(syntax::SyntaxKind::Token)),
- TokKind(uint16_t(tok.getKind())),
+ TokKind(uint16_t(tokKind)),
DK(DataKind::DeferredToken) {
- assert(getTokenKind() == tok.getKind() && "Token kind is too large value!");
+ assert(getTokenKind() == tokKind && "Token kind is too large value!");
+ assert(DeferredToken.NumLeadingTrivia == numLeadingTrivia &&
+ "numLeadingTrivia is too large value!");
+ assert(DeferredToken.NumTrailingTrivia == numTrailingTrivia &&
+ "numLeadingTrivia is too large value!");
}
public:
@@ -106,63 +115,6 @@
assert(getTokenKind() == tokKind && "Token kind with too large value!");
}
- ParsedRawSyntaxNode(const ParsedRawSyntaxNode &other) {
- switch (other.DK) {
- case DataKind::Null:
- break;
- case DataKind::Recorded:
- new(&this->RecordedData)RecordedSyntaxNode(other.RecordedData);
- break;
- case DataKind::DeferredLayout:
- new(&this->DeferredLayout)DeferredLayoutNode(other.DeferredLayout);
- break;
- case DataKind::DeferredToken:
- new(&this->DeferredToken)DeferredTokenNode(other.DeferredToken);
- break;
- }
- this->SynKind = other.SynKind;
- this->TokKind = other.TokKind;
- this->DK = other.DK;
- }
-
- ParsedRawSyntaxNode(ParsedRawSyntaxNode &&other) {
- switch (other.DK) {
- case DataKind::Null:
- break;
- case DataKind::Recorded:
- new(&this->RecordedData)RecordedSyntaxNode(
- std::move(other.RecordedData));
- break;
- case DataKind::DeferredLayout:
- new(&this->DeferredLayout)DeferredLayoutNode(
- std::move(other.DeferredLayout));
- break;
- case DataKind::DeferredToken:
- new(&this->DeferredToken)DeferredTokenNode(
- std::move(other.DeferredToken));
- break;
- }
- this->SynKind = other.SynKind;
- this->TokKind = other.TokKind;
- this->DK = other.DK;
- }
-
- ~ParsedRawSyntaxNode() {
- releaseMemory();
- }
-
- ParsedRawSyntaxNode &operator=(const ParsedRawSyntaxNode &other) {
- releaseMemory();
- new (this)ParsedRawSyntaxNode(other);
- return *this;
- }
-
- ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &&other) {
- releaseMemory();
- new (this)ParsedRawSyntaxNode(std::move(other));
- return *this;
- }
-
syntax::SyntaxKind getKind() const { return syntax::SyntaxKind(SynKind); }
tok getTokenKind() const { return tok(TokKind); }
@@ -201,44 +153,44 @@
assert(DK == DataKind::DeferredLayout);
return DeferredLayout.Children;
}
- void addDeferredChild(ParsedRawSyntaxNode subnode) {
- assert(DK == DataKind::DeferredLayout);
- DeferredLayout.Children.push_back(std::move(subnode));
- }
// Deferred Token Data =====================================================//
- const Token &getToken() const {
+ CharSourceRange getDeferredTokenRangeWithoutBackticks() const {
assert(DK == DataKind::DeferredToken);
- return DeferredToken.Tok;
+ return CharSourceRange{DeferredToken.TokLoc, DeferredToken.TokLength};
}
- const syntax::Trivia &getLeadingTrivia() const {
+ ArrayRef<ParsedTriviaPiece> getDeferredLeadingTriviaPieces() const {
assert(DK == DataKind::DeferredToken);
- return DeferredToken.LeadingTrivia;
+ return ArrayRef<ParsedTriviaPiece>(DeferredToken.TriviaPieces,
+ DeferredToken.NumLeadingTrivia);
}
- const syntax::Trivia &getTrailingTrivia() const {
+ ArrayRef<ParsedTriviaPiece> getDeferredTrailingTriviaPieces() const {
assert(DK == DataKind::DeferredToken);
- return DeferredToken.TrailingTrivia;
+ return ArrayRef<ParsedTriviaPiece>(
+ DeferredToken.TriviaPieces + DeferredToken.NumLeadingTrivia,
+ DeferredToken.NumTrailingTrivia);
}
//==========================================================================//
/// Form a deferred syntax layout node.
static ParsedRawSyntaxNode makeDeferred(syntax::SyntaxKind k,
- ArrayRef<ParsedRawSyntaxNode> deferredNodes) {
- return ParsedRawSyntaxNode{k, deferredNodes};
- }
+ ArrayRef<ParsedRawSyntaxNode> deferredNodes,
+ SyntaxParsingContext &ctx);
/// Form a deferred token node.
static ParsedRawSyntaxNode makeDeferred(Token tok,
- syntax::Trivia leadingTrivia,
- syntax::Trivia trailingTrivia) {
- return ParsedRawSyntaxNode{std::move(tok), std::move(leadingTrivia),
- std::move(trailingTrivia)};
- }
+ const ParsedTrivia &leadingTrivia,
+ const ParsedTrivia &trailingTrivia,
+ SyntaxParsingContext &ctx);
/// Form a deferred missing token node.
- static ParsedRawSyntaxNode makeDeferredMissing(tok tokKind, SourceLoc loc);
+ static ParsedRawSyntaxNode makeDeferredMissing(tok tokKind, SourceLoc loc) {
+ auto raw = ParsedRawSyntaxNode(tokKind, loc, 0, nullptr, 0, 0);
+ raw.IsMissing = true;
+ return raw;
+ }
/// Dump this piece of syntax recursively for debugging or testing.
LLVM_ATTRIBUTE_DEPRECATED(
@@ -251,20 +203,6 @@
static ParsedRawSyntaxNode null() {
return ParsedRawSyntaxNode{};
}
-
-private:
- void releaseMemory() {
- switch (DK) {
- case DataKind::Null:
- break;
- case DataKind::Recorded:
- RecordedData.~RecordedSyntaxNode(); break;
- case DataKind::DeferredLayout:
- DeferredLayout.~DeferredLayoutNode(); break;
- case DataKind::DeferredToken:
- DeferredToken.~DeferredTokenNode(); break;
- }
- }
};
} // end namespace swift
diff --git a/include/swift/Parse/ParsedRawSyntaxRecorder.h b/include/swift/Parse/ParsedRawSyntaxRecorder.h
index f43375e..9ab897b 100644
--- a/include/swift/Parse/ParsedRawSyntaxRecorder.h
+++ b/include/swift/Parse/ParsedRawSyntaxRecorder.h
@@ -24,7 +24,10 @@
namespace swift {
+class CharSourceRange;
class ParsedRawSyntaxNode;
+struct ParsedTrivia;
+class ParsedTriviaPiece;
class SyntaxParseActions;
class SourceLoc;
class Token;
@@ -32,7 +35,6 @@
namespace syntax {
enum class SyntaxKind;
- struct Trivia;
}
class ParsedRawSyntaxRecorder {
@@ -43,8 +45,12 @@
: SPActions(std::move(spActions)) {}
ParsedRawSyntaxNode recordToken(const Token &tok,
- const syntax::Trivia &leadingTrivia,
- const syntax::Trivia &trailingTrivia);
+ const ParsedTrivia &leadingTrivia,
+ const ParsedTrivia &trailingTrivia);
+
+ ParsedRawSyntaxNode recordToken(tok tokenKind, CharSourceRange tokenRange,
+ ArrayRef<ParsedTriviaPiece> leadingTrivia,
+ ArrayRef<ParsedTriviaPiece> trailingTrivia);
/// Record a missing token. \p loc can be invalid or an approximate location
/// of where the token would be if not missing.
diff --git a/include/swift/Parse/ParsedSyntaxBuilders.h.gyb b/include/swift/Parse/ParsedSyntaxBuilders.h.gyb
index 7a64c73..95d1f4e 100644
--- a/include/swift/Parse/ParsedSyntaxBuilders.h.gyb
+++ b/include/swift/Parse/ParsedSyntaxBuilders.h.gyb
@@ -34,17 +34,20 @@
% if node.is_buildable():
% child_count = len(node.children)
class Parsed${node.name}Builder {
- ParsedRawSyntaxRecorder &Rec;
- bool IsBacktracking;
- ParsedRawSyntaxNode Layout[${child_count}] = {
+ SyntaxParsingContext &SPCtx;
+ ParsedRawSyntaxNode Layout[${child_count}];
% for child in node.children:
- ParsedRawSyntaxNode::null(),
+% child_node = NODE_MAP.get(child.syntax_kind)
+% if child_node and child_node.is_syntax_collection():
+% child_elt = child_node.collection_element_name
+% child_elt_type = child_node.collection_element_type
+ SmallVector<ParsedRawSyntaxNode, 8> ${child_elt}Nodes;
+% end
% end
- };
public:
explicit Parsed${node.name}Builder(SyntaxParsingContext &SPCtx)
- : Rec(SPCtx.getRecorder()), IsBacktracking(SPCtx.isBacktracking()) {}
+ : SPCtx(SPCtx) {}
% for child in node.children:
Parsed${node.name}Builder &use${child.name}(Parsed${child.type_name} ${child.name});
@@ -61,7 +64,7 @@
private:
Parsed${node.name} record();
- void finishLayout();
+ void finishLayout(bool deferred);
};
% end
diff --git a/include/swift/Parse/ParsedSyntaxRecorder.h.gyb b/include/swift/Parse/ParsedSyntaxRecorder.h.gyb
index da0734a..631bce6 100644
--- a/include/swift/Parse/ParsedSyntaxRecorder.h.gyb
+++ b/include/swift/Parse/ParsedSyntaxRecorder.h.gyb
@@ -46,7 +46,8 @@
static Parsed${node.name} record${node.syntax_kind}(${child_params},
ParsedRawSyntaxRecorder &rec);
public:
- static Parsed${node.name} defer${node.syntax_kind}(${child_params});
+ static Parsed${node.name} defer${node.syntax_kind}(${child_params},
+ SyntaxParsingContext &SPCtx);
static Parsed${node.name} make${node.syntax_kind}(${child_params},
SyntaxParsingContext &SPCtx);
% elif node.is_syntax_collection():
@@ -57,7 +58,8 @@
public:
static Parsed${node.name} defer${node.syntax_kind}(
- ArrayRef<Parsed${node.collection_element_type}> elts);
+ ArrayRef<Parsed${node.collection_element_type}> elts,
+ SyntaxParsingContext &SPCtx);
static Parsed${node.name} make${node.syntax_kind}(
ArrayRef<Parsed${node.collection_element_type}> elts,
SyntaxParsingContext &SPCtx);
diff --git a/include/swift/Parse/ParsedTrivia.h b/include/swift/Parse/ParsedTrivia.h
new file mode 100644
index 0000000..8bf9e9f
--- /dev/null
+++ b/include/swift/Parse/ParsedTrivia.h
@@ -0,0 +1,136 @@
+//===--- ParsedTrivia.h - ParsedTrivia API ----------------------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_PARSE_PARSEDTRIVIA_H
+#define SWIFT_PARSE_PARSEDTRIVIA_H
+
+#include "swift/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace swift {
+ class SourceLoc;
+ class SourceManager;
+
+namespace syntax {
+ enum class TriviaKind;
+ struct Trivia;
+}
+
+class ParsedTriviaPiece {
+ syntax::TriviaKind Kind;
+ unsigned Length;
+
+public:
+ ParsedTriviaPiece(syntax::TriviaKind kind, unsigned length)
+ : Kind(kind), Length(length) {}
+
+ syntax::TriviaKind getKind() const { return Kind; }
+
+ /// Return the text of the trivia.
+ unsigned getLength() const { return Length; }
+
+ void extendLength(unsigned len) {
+ Length += len;
+ }
+
+ static size_t getTotalLength(ArrayRef<ParsedTriviaPiece> pieces) {
+ size_t Len = 0;
+ for (auto &p : pieces)
+ Len += p.getLength();
+ return Len;
+ }
+
+ bool operator==(const ParsedTriviaPiece &Other) const {
+ return Kind == Other.Kind && Length == Other.Length;
+ }
+
+ bool operator!=(const ParsedTriviaPiece &Other) const {
+ return !(*this == Other);
+ }
+
+ static syntax::Trivia
+ convertToSyntaxTrivia(ArrayRef<ParsedTriviaPiece> pieces, SourceLoc loc,
+ const SourceManager &SM, unsigned bufferID);
+};
+
+using ParsedTriviaList = SmallVector<ParsedTriviaPiece, 3>;
+
+struct ParsedTrivia {
+ ParsedTriviaList Pieces;
+
+ /// Get the begin iterator of the pieces.
+ ParsedTriviaList::const_iterator begin() const {
+ return Pieces.begin();
+ }
+
+ /// Get the end iterator of the pieces.
+ ParsedTriviaList::const_iterator end() const {
+ return Pieces.end();
+ }
+
+ /// Clear pieces.
+ void clear() {
+ Pieces.clear();
+ }
+
+ /// Returns true if there are no pieces in this Trivia collection.
+ bool empty() const {
+ return Pieces.empty();
+ }
+
+ /// Return the number of pieces in this Trivia collection.
+ size_t size() const {
+ return Pieces.size();
+ }
+
+ size_t getLength() const {
+ return ParsedTriviaPiece::getTotalLength(Pieces);
+ }
+
+ void push_back(syntax::TriviaKind kind, unsigned length) {
+ Pieces.emplace_back(kind, length);
+ }
+
+ void appendOrSquash(syntax::TriviaKind kind, unsigned length) {
+ if (empty() || Pieces.back().getKind() != kind) {
+ push_back(kind, length);
+ } else {
+ Pieces.back().extendLength(length);
+ }
+ }
+
+ bool operator==(const ParsedTrivia &Other) const {
+ if (Pieces.size() != Other.size()) {
+ return false;
+ }
+
+ for (size_t i = 0; i < Pieces.size(); ++i) {
+ if (Pieces[i] != Other.Pieces[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool operator!=(const ParsedTrivia &Other) const {
+ return !(*this == Other);
+ }
+
+ syntax::Trivia convertToSyntaxTrivia(SourceLoc loc, const SourceManager &SM,
+ unsigned bufferID) const;
+};
+
+} // end namespace swift
+
+#endif
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 4bd61f3..bff4bc7 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -33,6 +33,7 @@
#include "swift/Parse/ParserResult.h"
#include "swift/Parse/SyntaxParserResult.h"
#include "swift/Parse/SyntaxParsingContext.h"
+#include "swift/Syntax/References.h"
#include "swift/Config.h"
#include "llvm/ADT/SetVector.h"
@@ -164,7 +165,9 @@
DelayedParsingCallbacks *DelayedParseCB = nullptr;
- bool isDelayedParsingEnabled() const { return DelayedParseCB != nullptr; }
+ bool isDelayedParsingEnabled() const {
+ return DelayBodyParsing || DelayedParseCB != nullptr;
+ }
void setDelayedParsingCallbacks(DelayedParsingCallbacks *DelayedParseCB) {
this->DelayedParseCB = DelayedParseCB;
@@ -200,14 +203,21 @@
/// leading trivias for \c Tok.
/// Always empty if !SF.shouldBuildSyntaxTree().
- syntax::Trivia LeadingTrivia;
+ ParsedTrivia LeadingTrivia;
/// trailing trivias for \c Tok.
/// Always empty if !SF.shouldBuildSyntaxTree().
- syntax::Trivia TrailingTrivia;
+ ParsedTrivia TrailingTrivia;
- /// Whether we should disable delayed parsing.
- bool DisableDelayedParsing;
+ /// Whether we should delay parsing nominal type and extension bodies,
+ /// and skip function bodies.
+ ///
+ /// This is false in primary files, since we want to type check all
+ /// declarations and function bodies.
+ ///
+ /// This is true for non-primary files, where declarations only need to be
+ /// lazily parsed and type checked.
+ bool DelayBodyParsing;
/// The receiver to collect all consumed tokens.
ConsumeTokenReceiver *TokReceiver;
@@ -356,16 +366,16 @@
SILParserTUStateBase *SIL,
PersistentParserState *PersistentState,
std::shared_ptr<SyntaxParseActions> SPActions = nullptr,
- bool DisableDelayedParsing = false);
+ bool DelayBodyParsing = true);
Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
PersistentParserState *PersistentState = nullptr,
std::shared_ptr<SyntaxParseActions> SPActions = nullptr,
- bool DisableDelayedParsing = false);
+ bool DelayBodyParsing = true);
Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF,
SILParserTUStateBase *SIL = nullptr,
PersistentParserState *PersistentState = nullptr,
std::shared_ptr<SyntaxParseActions> SPActions = nullptr,
- bool DisableDelayedParsing = false);
+ bool DelayBodyParsing = true);
~Parser();
bool isInSILMode() const { return SIL != nullptr; }
@@ -636,6 +646,9 @@
/// Add the given Decl to the current scope.
void addToScope(ValueDecl *D) {
+ if (Context.LangOpts.EnableASTScopeLookup)
+ return;
+
getScopeInfo().addToScope(D, *this);
}
@@ -794,6 +807,13 @@
void parseDeclListDelayed(IterableDeclContext *IDC);
+ bool canDelayMemberDeclParsing();
+
+ bool delayParsingDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
+ SourceLoc PosBeforeLB,
+ ParseDeclOptions Options,
+ IterableDeclContext *IDC);
+
ParserResult<TypeDecl> parseDeclTypeAlias(ParseDeclOptions Flags,
DeclAttributes &Attributes);
@@ -890,7 +910,7 @@
llvm::function_ref<void(Decl*)> handler);
bool parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
Diag<> ErrorDiag, ParseDeclOptions Options,
- llvm::function_ref<void(Decl*)> handler);
+ IterableDeclContext *IDC);
ParserResult<ExtensionDecl> parseDeclExtension(ParseDeclOptions Flags,
DeclAttributes &Attributes);
ParserResult<EnumDecl> parseDeclEnum(ParseDeclOptions Flags,
@@ -1424,8 +1444,6 @@
parsePlatformVersionConstraintSpec();
ParserResult<PlatformAgnosticVersionConstraintAvailabilitySpec>
parsePlatformAgnosticVersionConstraintSpec();
-
- bool canDelayMemberDeclParsing();
};
/// Describes a parsed declaration name.
diff --git a/include/swift/Parse/SyntaxParseActions.h b/include/swift/Parse/SyntaxParseActions.h
index 9bcd27c..1c12fa0 100644
--- a/include/swift/Parse/SyntaxParseActions.h
+++ b/include/swift/Parse/SyntaxParseActions.h
@@ -23,13 +23,12 @@
namespace swift {
class CharSourceRange;
+class ParsedTriviaPiece;
class SourceLoc;
-class Token;
enum class tok;
namespace syntax {
enum class SyntaxKind;
- struct Trivia;
}
typedef void *OpaqueSyntaxNode;
@@ -40,10 +39,10 @@
public:
virtual ~SyntaxParseActions() = default;
- virtual OpaqueSyntaxNode recordToken(const Token &tok,
- const syntax::Trivia &leadingTrivia,
- const syntax::Trivia &trailingTrivia,
- CharSourceRange range) = 0;
+ virtual OpaqueSyntaxNode recordToken(tok tokenKind,
+ ArrayRef<ParsedTriviaPiece> leadingTrivia,
+ ArrayRef<ParsedTriviaPiece> trailingTrivia,
+ CharSourceRange range) = 0;
/// Record a missing token. \c loc can be invalid or an approximate location
/// of where the token would be if not missing.
diff --git a/include/swift/Parse/SyntaxParsingContext.h b/include/swift/Parse/SyntaxParsingContext.h
index 527ea3e..4dfeacb 100644
--- a/include/swift/Parse/SyntaxParsingContext.h
+++ b/include/swift/Parse/SyntaxParsingContext.h
@@ -24,6 +24,7 @@
class ParsedSyntax;
class ParsedTokenSyntax;
+struct ParsedTrivia;
class SourceFile;
enum class tok;
class Token;
@@ -93,6 +94,8 @@
ParsedRawSyntaxRecorder Recorder;
+ llvm::BumpPtrAllocator ScratchAlloc;
+
RootContextData(SourceFile &SF, DiagnosticEngine &Diags,
SourceManager &SourceMgr, unsigned BufferID,
std::shared_ptr<SyntaxParseActions> spActions)
@@ -241,12 +244,16 @@
ParsedRawSyntaxRecorder &getRecorder() { return getRootData()->Recorder; }
+ llvm::BumpPtrAllocator &getScratchAlloc() {
+ return getRootData()->ScratchAlloc;
+ }
+
/// Add RawSyntax to the parts.
void addRawSyntax(ParsedRawSyntaxNode Raw);
/// Add Token with Trivia to the parts.
- void addToken(Token &Tok, Trivia &LeadingTrivia,
- Trivia &TrailingTrivia);
+ void addToken(Token &Tok, const ParsedTrivia &LeadingTrivia,
+ const ParsedTrivia &TrailingTrivia);
/// Add Syntax to the parts.
void addSyntax(ParsedSyntax Node);
diff --git a/include/swift/Parse/Token.h b/include/swift/Parse/Token.h
index c13f585..d607ad3 100644
--- a/include/swift/Parse/Token.h
+++ b/include/swift/Parse/Token.h
@@ -248,6 +248,17 @@
return CharSourceRange(getLoc(), getLength());
}
+ CharSourceRange getRangeWithoutBackticks() const {
+ SourceLoc TokLoc = getLoc();
+ unsigned TokLength = getLength();
+ if (isEscapedIdentifier()) {
+ // Adjust to account for the backticks.
+ TokLoc = TokLoc.getAdvancedLoc(1);
+ TokLength -= 2;
+ }
+ return CharSourceRange(TokLoc, TokLength);
+ }
+
bool hasComment() const {
return CommentLength != 0;
}
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 216d45e..5bb0bf7 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -327,10 +327,12 @@
// Type remapping
//===--------------------------------------------------------------------===//
- static SILType getPartialApplyResultType(SILType Ty, unsigned ArgCount,
- SILModule &M,
- SubstitutionMap subs,
- ParameterConvention calleeConvention);
+ static SILType
+ getPartialApplyResultType(SILType Ty, unsigned ArgCount, SILModule &M,
+ SubstitutionMap subs,
+ ParameterConvention calleeConvention,
+ PartialApplyInst::OnStackKind onStack =
+ PartialApplyInst::OnStackKind::NotOnStack);
//===--------------------------------------------------------------------===//
// CFG Manipulation
@@ -476,10 +478,12 @@
PartialApplyInst *createPartialApply(
SILLocation Loc, SILValue Fn, SubstitutionMap Subs,
ArrayRef<SILValue> Args, ParameterConvention CalleeConvention,
+ PartialApplyInst::OnStackKind OnStack =
+ PartialApplyInst::OnStackKind::NotOnStack,
const GenericSpecializationInformation *SpecializationInfo = nullptr) {
return insert(PartialApplyInst::create(
getSILDebugLocation(Loc), Fn, Args, Subs, CalleeConvention, *F,
- C.OpenedArchetypes, SpecializationInfo));
+ C.OpenedArchetypes, SpecializationInfo, OnStack));
}
BeginApplyInst *createBeginApply(
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 47f2e6c..0b22037 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -878,6 +878,7 @@
getOpLocation(Inst->getLoc()), getOpValue(Inst->getCallee()),
getOpSubstitutionMap(Inst->getSubstitutionMap()), Args,
Inst->getType().getAs<SILFunctionType>()->getCalleeConvention(),
+ Inst->isOnStack(),
GenericSpecializationInformation::create(Inst, getBuilder())));
}
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 1899b00..7402e77 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -2072,6 +2072,12 @@
public llvm::TrailingObjects<PartialApplyInst, Operand> {
friend SILBuilder;
+public:
+ enum OnStackKind {
+ NotOnStack, OnStack
+ };
+
+private:
PartialApplyInst(SILDebugLocation DebugLoc, SILValue Callee,
SILType SubstCalleeType,
SubstitutionMap Substitutions,
@@ -2084,7 +2090,8 @@
create(SILDebugLocation DebugLoc, SILValue Callee, ArrayRef<SILValue> Args,
SubstitutionMap Substitutions, ParameterConvention CalleeConvention,
SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes,
- const GenericSpecializationInformation *SpecializationInfo);
+ const GenericSpecializationInformation *SpecializationInfo,
+ OnStackKind onStack);
public:
/// Return the result function type of this partial apply.
@@ -2094,6 +2101,10 @@
bool hasCalleeGuaranteedContext() const {
return getType().castTo<SILFunctionType>()->isCalleeGuaranteed();
}
+
+ OnStackKind isOnStack() const {
+ return getFunctionType()->isNoEscape() ? OnStack : NotOnStack;
+ }
};
class BeginApplyInst;
diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h
index 13ef594..738b7fb 100644
--- a/include/swift/SIL/TypeSubstCloner.h
+++ b/include/swift/SIL/TypeSubstCloner.h
@@ -215,8 +215,8 @@
PartialApplyInst *N = getBuilder().createPartialApply(
getOpLocation(Inst->getLoc()), Helper.getCallee(),
Helper.getSubstitutions(), Helper.getArguments(), ParamConvention,
- GenericSpecializationInformation::create(
- Inst, getBuilder()));
+ Inst->isOnStack(),
+ GenericSpecializationInformation::create(Inst, getBuilder()));
recordClonedInstruction(Inst, N);
}
diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def
index f14f51d..6ff5215 100644
--- a/include/swift/SILOptimizer/PassManager/Passes.def
+++ b/include/swift/SILOptimizer/PassManager/Passes.def
@@ -232,8 +232,10 @@
"Performance Function Inlining")
PASS(PerformanceConstantPropagation, "performance-constant-propagation",
"Constant Propagation for Performance without Diagnostics")
-PASS(PredictableMemoryOptimizations, "predictable-memopt",
- "Predictable Memory Optimization for Diagnostics")
+PASS(PredictableMemoryAccessOptimizations, "predictable-memaccess-opts",
+ "Predictable Memory Access Optimizations for Diagnostics")
+PASS(PredictableDeadAllocationElimination, "predictable-deadalloc-elim",
+ "Eliminate dead temporary allocations after diagnostics")
PASS(ReleaseDevirtualizer, "release-devirtualizer",
"SIL release Devirtualization")
PASS(RetainSinking, "retain-sinking",
diff --git a/include/swift/SILOptimizer/Utils/Local.h b/include/swift/SILOptimizer/Utils/Local.h
index 7548c4a..34ef9fb 100644
--- a/include/swift/SILOptimizer/Utils/Local.h
+++ b/include/swift/SILOptimizer/Utils/Local.h
@@ -212,6 +212,12 @@
SILBuilder &Builder, SILLocation Loc, SILValue Arg, SILParameterInfo PInfo,
InstModCallbacks Callbacks = InstModCallbacks());
+/// Insert destroys of captured arguments of partial_apply [stack].
+void insertDestroyOfCapturedArguments(
+ PartialApplyInst *PAI, SILBuilder &B,
+ llvm::function_ref<bool(SILValue)> shouldInsertDestroy =
+ [](SILValue arg) -> bool { return true; });
+
/// This computes the lifetime of a single SILValue.
///
/// This does not compute a set of jointly postdominating use points. Instead it
diff --git a/include/swift/SILOptimizer/Utils/StackNesting.h b/include/swift/SILOptimizer/Utils/StackNesting.h
index 988b3a5..8f71334 100644
--- a/include/swift/SILOptimizer/Utils/StackNesting.h
+++ b/include/swift/SILOptimizer/Utils/StackNesting.h
@@ -98,10 +98,10 @@
///
/// Each stack location is allocated by a single allocation instruction.
struct StackLoc {
- StackLoc(AllocationInst *Alloc) : Alloc(Alloc) { }
+ StackLoc(SingleValueInstruction *Alloc) : Alloc(Alloc) { }
/// Back-link to the allocation instruction.
- AllocationInst *Alloc;
+ SingleValueInstruction *Alloc;
/// Bit-set which represents all alive locations at this allocation.
/// It obviously includes this location itself. And it includes all "outer"
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 6c48b5f..6373887 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -52,7 +52,7 @@
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t SWIFTMODULE_VERSION_MINOR = 471; // Last change: Add @available(_PackageDescription..)
+const uint16_t SWIFTMODULE_VERSION_MINOR = 472; // Last change: partial_apply [stack]
using DeclIDField = BCFixed<31>;
diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h
index 0d1323f..673e8e6 100644
--- a/include/swift/Subsystems.h
+++ b/include/swift/Subsystems.h
@@ -122,7 +122,7 @@
SILParserState *SIL = nullptr,
PersistentParserState *PersistentState = nullptr,
DelayedParsingCallbacks *DelayedParseCB = nullptr,
- bool DisableDelayedParsing = false);
+ bool DelayBodyParsing = true);
/// Parse a single buffer into the given source file, until the full source
/// contents are parsed.
@@ -131,7 +131,7 @@
bool parseIntoSourceFileFull(SourceFile &SF, unsigned BufferID,
PersistentParserState *PersistentState = nullptr,
DelayedParsingCallbacks *DelayedParseCB = nullptr,
- bool DisableDelayedParsing = false);
+ bool DelayBodyParsing = true);
/// Finish the parsing by going over the nodes that were delayed
/// during the first parsing pass.
diff --git a/include/swift/Syntax/Trivia.h.gyb b/include/swift/Syntax/Trivia.h.gyb
index 622c09a..0f8994c 100644
--- a/include/swift/Syntax/Trivia.h.gyb
+++ b/include/swift/Syntax/Trivia.h.gyb
@@ -109,6 +109,8 @@
% end
};
+bool isCommentTriviaKind(TriviaKind kind);
+
/// A contiguous stretch of a single kind of trivia. The constituent part of
/// a `Trivia` collection.
///
@@ -150,6 +152,8 @@
% end
% end
+ static TriviaPiece fromText(TriviaKind kind, StringRef text);
+
/// Return kind of the trivia.
TriviaKind getKind() const { return Kind; }
@@ -174,7 +178,9 @@
llvm_unreachable("unhandled kind");
}
- bool isComment() const;
+ bool isComment() const {
+ return isCommentTriviaKind(getKind());
+ }
void accumulateAbsolutePosition(AbsolutePosition &Pos) const;
diff --git a/include/swift/SyntaxParse/SyntaxTreeCreator.h b/include/swift/SyntaxParse/SyntaxTreeCreator.h
index c8ad55e..3ed4496 100644
--- a/include/swift/SyntaxParse/SyntaxTreeCreator.h
+++ b/include/swift/SyntaxParse/SyntaxTreeCreator.h
@@ -18,6 +18,7 @@
namespace swift {
class RawSyntaxTokenCache;
+ class SourceManager;
class SyntaxParsingCache;
class SourceFile;
@@ -32,6 +33,8 @@
/// It also handles caching re-usable RawSyntax objects and skipping parsed
/// nodes via consulting a \c SyntaxParsingCache.
class SyntaxTreeCreator: public SyntaxParseActions {
+ SourceManager &SM;
+ unsigned BufferID;
RC<syntax::SyntaxArena> Arena;
/// A cache of nodes that can be reused when creating the current syntax
@@ -43,16 +46,17 @@
std::unique_ptr<RawSyntaxTokenCache> TokenCache;
public:
- SyntaxTreeCreator(SyntaxParsingCache *syntaxCache,
+ SyntaxTreeCreator(SourceManager &SM, unsigned bufferID,
+ SyntaxParsingCache *syntaxCache,
RC<syntax::SyntaxArena> arena);
~SyntaxTreeCreator();
void acceptSyntaxRoot(OpaqueSyntaxNode root, SourceFile &SF);
private:
- OpaqueSyntaxNode recordToken(const Token &tok,
- const syntax::Trivia &leadingTrivia,
- const syntax::Trivia &trailingTrivia,
+ OpaqueSyntaxNode recordToken(tok tokenKind,
+ ArrayRef<ParsedTriviaPiece> leadingTrivia,
+ ArrayRef<ParsedTriviaPiece> trailingTrivia,
CharSourceRange range) override;
OpaqueSyntaxNode recordMissingToken(tok tokenKind, SourceLoc loc) override;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 8231708..9dfddd5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -42,6 +42,7 @@
#include "swift/Basic/Statistic.h"
#include "swift/Basic/StringExtras.h"
#include "swift/Parse/Lexer.h" // bad dependency
+#include "swift/Syntax/References.h"
#include "swift/Syntax/SyntaxArena.h"
#include "swift/Strings.h"
#include "swift/Subsystems.h"
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 99b58cc..772d879 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -1331,6 +1331,10 @@
case DeclContextKind::SubscriptDecl:
printName(os, cast<SubscriptDecl>(dc)->getFullName());
break;
+
+ case DeclContextKind::EnumElementDecl:
+ printName(os, cast<EnumElementDecl>(dc)->getFullName());
+ break;
}
}
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 76faaf8..71d351e 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -1508,6 +1508,11 @@
return appendEntity(fn);
}
+ case DeclContextKind::EnumElementDecl: {
+ auto eed = cast<EnumElementDecl>(ctx);
+ return appendEntity(eed);
+ }
+
case DeclContextKind::SubscriptDecl:
// FIXME: We may need to do something here if subscripts contain any symbols
// exposed with linkage names, or if/when they get generic parameters.
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 1b84fd6..26b4b24 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -750,6 +750,7 @@
FUNCTION_LIKE(ConstructorDecl)
FUNCTION_LIKE(DestructorDecl)
FUNCTION_LIKE(FuncDecl)
+ FUNCTION_LIKE(EnumElementDecl)
SCOPE_LIKE(NominalTypeDecl)
SCOPE_LIKE(ExtensionDecl)
diff --git a/lib/AST/AccessRequests.cpp b/lib/AST/AccessRequests.cpp
index 198baba..19640fb 100644
--- a/lib/AST/AccessRequests.cpp
+++ b/lib/AST/AccessRequests.cpp
@@ -105,6 +105,7 @@
case DeclContextKind::Initializer:
case DeclContextKind::AbstractFunctionDecl:
case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::EnumElementDecl:
return AccessLevel::Private;
case DeclContextKind::Module:
case DeclContextKind::FileUnit:
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 8a30842..a33bddc 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3547,7 +3547,6 @@
// Create an empty body for the destructor.
DD->setBody(BraceStmt::create(ctx, getLoc(), { }, getLoc(), true));
addMember(DD);
- setHasDestructor();
// Propagate access control and versioned-ness.
DD->copyFormalAccessFrom(this, /*sourceIsParentContext*/true);
@@ -3910,16 +3909,19 @@
Bits.ProtocolDecl.ExistentialConformsToSelf = false;
Bits.ProtocolDecl.Circularity
= static_cast<unsigned>(CircularityCheck::Unchecked);
+ Bits.ProtocolDecl.InheritedProtocolsValid = 0;
Bits.ProtocolDecl.NumRequirementsInSignature = 0;
Bits.ProtocolDecl.HasMissingRequirements = false;
Bits.ProtocolDecl.KnownProtocol = 0;
- setTrailingWhereClause(TrailingWhere);
+ setTrailingWhereClause(TrailingWhere);
}
-llvm::TinyPtrVector<ProtocolDecl *>
-ProtocolDecl::getInheritedProtocols() const {
- llvm::TinyPtrVector<ProtocolDecl *> result;
- SmallPtrSet<const ProtocolDecl *, 4> known;
+ArrayRef<ProtocolDecl *>
+ProtocolDecl::getInheritedProtocolsSlow() {
+ Bits.ProtocolDecl.InheritedProtocolsValid = true;
+
+ llvm::SmallVector<ProtocolDecl *, 2> result;
+ SmallPtrSet<const ProtocolDecl *, 2> known;
known.insert(this);
bool anyObject = false;
for (const auto found :
@@ -3931,7 +3933,9 @@
}
}
- return result;
+ auto &ctx = getASTContext();
+ InheritedProtocols = ctx.AllocateCopy(result);
+ return InheritedProtocols;
}
llvm::TinyPtrVector<AssociatedTypeDecl *>
@@ -3973,7 +3977,10 @@
void ProtocolDecl::setSuperclass(Type superclass) {
assert((!superclass || !superclass->hasArchetype())
&& "superclass must be interface type");
- LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
+ LazySemanticInfo.SuperclassType.setPointerAndInt(superclass, true);
+ LazySemanticInfo.SuperclassDecl.setPointerAndInt(
+ superclass ? superclass->getClassOrBoundGenericClass() : nullptr,
+ true);
}
bool ProtocolDecl::walkInheritedProtocols(
@@ -6478,7 +6485,10 @@
void ClassDecl::setSuperclass(Type superclass) {
assert((!superclass || !superclass->hasArchetype())
&& "superclass must be interface type");
- LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
+ LazySemanticInfo.SuperclassType.setPointerAndInt(superclass, true);
+ LazySemanticInfo.SuperclassDecl.setPointerAndInt(
+ superclass ? superclass->getClassOrBoundGenericClass() : nullptr,
+ true);
}
ClangNode Decl::getClangNodeImpl() const {
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 4694e95..1c4d610 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -405,6 +405,9 @@
case DeclContextKind::SubscriptDecl:
break;
+ case DeclContextKind::EnumElementDecl:
+ break;
+
case DeclContextKind::Module:
case DeclContextKind::FileUnit:
return true;
@@ -461,6 +464,8 @@
return cast<AbstractFunctionDecl>(this)->walk(Walker);
case DeclContextKind::SubscriptDecl:
return cast<SubscriptDecl>(this)->walk(Walker);
+ case DeclContextKind::EnumElementDecl:
+ return cast<EnumElementDecl>(this)->walk(Walker);
case DeclContextKind::SerializedLocal:
llvm_unreachable("walk is unimplemented for deserialized contexts");
case DeclContextKind::Initializer:
@@ -547,6 +552,7 @@
Kind = "AbstractFunctionDecl";
break;
case DeclContextKind::SubscriptDecl: Kind = "SubscriptDecl"; break;
+ case DeclContextKind::EnumElementDecl: Kind = "EnumElementDecl"; break;
}
OS.indent(Depth*2 + indent) << (void*)this << " " << Kind;
@@ -601,6 +607,15 @@
OS << " : (no type set)";
break;
}
+ case DeclContextKind::EnumElementDecl: {
+ auto *EED = cast<EnumElementDecl>(this);
+ OS << " name=" << EED->getBaseName();
+ if (EED->hasInterfaceType())
+ OS << " : " << EED->getInterfaceType();
+ else
+ OS << " : (no type set)";
+ break;
+ }
case DeclContextKind::Initializer:
switch (cast<Initializer>(this)->getInitializerKind()) {
case InitializerKind::PatternBinding: {
@@ -920,6 +935,8 @@
return DeclContextKind::TopLevelCodeDecl;
case DeclKind::Subscript:
return DeclContextKind::SubscriptDecl;
+ case DeclKind::EnumElement:
+ return DeclContextKind::EnumElementDecl;
case DeclKind::Extension:
return DeclContextKind::ExtensionDecl;
default:
diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp
index ea80bc4..6fb8d11 100644
--- a/lib/AST/DiagnosticEngine.cpp
+++ b/lib/AST/DiagnosticEngine.cpp
@@ -767,6 +767,7 @@
case DeclContextKind::AbstractClosureExpr:
case DeclContextKind::AbstractFunctionDecl:
case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::EnumElementDecl:
break;
}
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index f3ca6bc..220c8d4 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -594,6 +594,14 @@
auto *extDecl = decl.dyn_cast<ExtensionDecl *>();
DeclContext *dc = protoDecl ? (DeclContext *)protoDecl : (DeclContext *)extDecl;
+
+ // A protocol or extension 'where' clause can reference associated types of
+ // the protocol itself, so we have to start unqualified lookup from 'dc'.
+ //
+ // However, the right hand side of a 'Self' conformance constraint must be
+ // resolved before unqualified lookup into 'dc' can work, so we make an
+ // exception here and begin lookup from the parent context instead.
+ auto *lookupDC = dc->getParent();
auto requirements = protoDecl ? protoDecl->getTrailingWhereClause()
: extDecl->getTrailingWhereClause();
@@ -623,7 +631,7 @@
// Resolve the right-hand side.
DirectlyReferencedTypeDecls rhsDecls;
if (auto typeRepr = req.getConstraintRepr()) {
- rhsDecls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, dc);
+ rhsDecls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, lookupDC);
} else if (Type type = req.getConstraint()) {
rhsDecls = directReferencesForType(type);
}
@@ -1437,6 +1445,11 @@
}
void NominalTypeDecl::addedMember(Decl *member) {
+ // Remember if we added a destructor.
+ if (auto *CD = dyn_cast<ClassDecl>(this))
+ if (isa<DestructorDecl>(member))
+ CD->setHasDestructor();
+
// If we have a lookup table, add the new member to it.
if (LookupTable.getPointer()) {
LookupTable.getPointer()->addMember(member);
diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp
index 245e6ca..0a82db6 100644
--- a/lib/AST/NameLookupRequests.cpp
+++ b/lib/AST/NameLookupRequests.cpp
@@ -74,6 +74,30 @@
//----------------------------------------------------------------------------//
// Superclass declaration computation.
//----------------------------------------------------------------------------//
+Optional<ClassDecl *> SuperclassDeclRequest::getCachedResult() const {
+ auto nominalDecl = std::get<0>(getStorage());
+
+ if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+ if (classDecl->LazySemanticInfo.SuperclassDecl.getInt())
+ return classDecl->LazySemanticInfo.SuperclassDecl.getPointer();
+
+ if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+ if (protocolDecl->LazySemanticInfo.SuperclassDecl.getInt())
+ return protocolDecl->LazySemanticInfo.SuperclassDecl.getPointer();
+
+ return None;
+}
+
+void SuperclassDeclRequest::cacheResult(ClassDecl *value) const {
+ auto nominalDecl = std::get<0>(getStorage());
+
+ if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+ classDecl->LazySemanticInfo.SuperclassDecl.setPointerAndInt(value, true);
+
+ if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+ protocolDecl->LazySemanticInfo.SuperclassDecl.setPointerAndInt(value, true);
+}
+
void SuperclassDeclRequest::diagnoseCycle(DiagnosticEngine &diags) const {
// FIXME: Improve this diagnostic.
auto subjectDecl = std::get<0>(getStorage());
@@ -87,7 +111,7 @@
}
//----------------------------------------------------------------------------//
-// Superclass declaration computation.
+// Extended nominal computation.
//----------------------------------------------------------------------------//
Optional<NominalTypeDecl *> ExtendedNominalRequest::getCachedResult() const {
// Note: if we fail to compute any nominal declaration, it's considered
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 6f250bc..163b560 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -2683,6 +2683,12 @@
substFn->getResult(), getExtInfo());
}
+CanFunctionType
+CanGenericFunctionType::substGenericArgs(SubstitutionMap subs) const {
+ return cast<FunctionType>(
+ getPointer()->substGenericArgs(subs)->getCanonicalType());
+}
+
static Type getMemberForBaseType(LookupConformanceFn lookupConformances,
Type origBase,
Type substBase,
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
index 442adcb..466ff7c 100644
--- a/lib/AST/TypeCheckRequests.cpp
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -125,12 +125,12 @@
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
- if (classDecl->LazySemanticInfo.Superclass.getInt())
- return classDecl->LazySemanticInfo.Superclass.getPointer();
+ if (classDecl->LazySemanticInfo.SuperclassType.getInt())
+ return classDecl->LazySemanticInfo.SuperclassType.getPointer();
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
- if (protocolDecl->LazySemanticInfo.Superclass.getInt())
- return protocolDecl->LazySemanticInfo.Superclass.getPointer();
+ if (protocolDecl->LazySemanticInfo.SuperclassType.getInt())
+ return protocolDecl->LazySemanticInfo.SuperclassType.getPointer();
return None;
}
@@ -139,10 +139,10 @@
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
- classDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+ classDecl->LazySemanticInfo.SuperclassType.setPointerAndInt(value, true);
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
- protocolDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+ protocolDecl->LazySemanticInfo.SuperclassType.setPointerAndInt(value, true);
}
//----------------------------------------------------------------------------//
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 250ce99..bd3ae67 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -1165,6 +1165,14 @@
if (!DummyIncludeBuffer.isValid()) {
clang::SourceLocation includeLoc =
srcMgr.getLocForStartOfFile(srcMgr.getMainFileID());
+ // Picking the beginning of the main FileID as include location is also what
+ // the clang PCH mechanism is doing (see
+ // clang::ASTReader::getImportLocation()). Choose the next source location
+ // here to avoid having the exact same import location as the clang PCH.
+ // Otherwise, if we are using a PCH for bridging header, we'll have
+ // problems with source order comparisons of clang source locations not
+ // being deterministic.
+ includeLoc = includeLoc.getLocWithOffset(1);
DummyIncludeBuffer = srcMgr.createFileID(
llvm::make_unique<ZeroFilledMemoryBuffer>(
256*1024, StringRef(moduleImportBufferName)),
@@ -1344,7 +1352,12 @@
return true;
}
- llvm::SmallString<128> importLine{"#import \""};
+ llvm::SmallString<128> importLine;
+ if (Impl.SwiftContext.LangOpts.EnableObjCInterop)
+ importLine = "#import \"";
+ else
+ importLine = "#include \"";
+
importLine += header;
importLine += "\"\n";
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 3c2bb2b..5566c6d 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -735,12 +735,10 @@
}
std::unique_ptr<DelayedParsingCallbacks>
-CompilerInstance::computeDelayedParsingCallback(bool isPrimary) {
+CompilerInstance::computeDelayedParsingCallback() {
if (Invocation.isCodeCompletion())
return llvm::make_unique<CodeCompleteDelayedCallbacks>(
SourceMgr.getCodeCompletionLoc());
- if (!isPrimary)
- return llvm::make_unique<AlwaysDelayedCallbacks>();
return nullptr;
}
@@ -754,22 +752,13 @@
void CompilerInstance::parseAndCheckTypesUpTo(
const ImplicitImports &implicitImports, SourceFile::ASTStage_t limitStage) {
FrontendStatsTracer tracer(Context->Stats, "parse-and-check-types");
- // Delayed parsing callback for the primary file, or all files
- // in non-WMO mode.
- std::unique_ptr<DelayedParsingCallbacks> PrimaryDelayedCB{
- computeDelayedParsingCallback(true)};
-
- // Delayed parsing callback for non-primary files. Not used in
- // WMO mode.
- std::unique_ptr<DelayedParsingCallbacks> SecondaryDelayedCB{
- computeDelayedParsingCallback(false)};
+ std::unique_ptr<DelayedParsingCallbacks> DelayedCB{
+ computeDelayedParsingCallback()};
PersistentParserState PersistentState(getASTContext());
bool hadLoadError = parsePartialModulesAndLibraryFiles(
- implicitImports, PersistentState,
- PrimaryDelayedCB.get(),
- SecondaryDelayedCB.get());
+ implicitImports, PersistentState, DelayedCB.get());
if (Invocation.isCodeCompletion()) {
// When we are doing code completion, make sure to emit at least one
// diagnostic, so that ASTContext is marked as erroneous. In this case
@@ -788,7 +777,7 @@
// interwined.
if (MainBufferID != NO_SUCH_BUFFER) {
parseAndTypeCheckMainFileUpTo(limitStage, PersistentState,
- PrimaryDelayedCB.get(), TypeCheckOptions);
+ DelayedCB.get(), TypeCheckOptions);
}
assert(llvm::all_of(MainModule->getFiles(), [](const FileUnit *File) -> bool {
@@ -829,8 +818,7 @@
void CompilerInstance::parseLibraryFile(
unsigned BufferID, const ImplicitImports &implicitImports,
PersistentParserState &PersistentState,
- DelayedParsingCallbacks *PrimaryDelayedCB,
- DelayedParsingCallbacks *SecondaryDelayedCB) {
+ DelayedParsingCallbacks *DelayedCB) {
FrontendStatsTracer tracer(Context->Stats, "parse-library-file");
auto *NextInput = createSourceFileForMainModule(
@@ -838,7 +826,6 @@
addAdditionalInitialImportsTo(NextInput, implicitImports);
auto IsPrimary = isWholeModuleCompilation() || isPrimaryInput(BufferID);
- auto *DelayedCB = IsPrimary ? PrimaryDelayedCB : SecondaryDelayedCB;
auto &Diags = NextInput->getASTContext().Diags;
auto DidSuppressWarnings = Diags.getSuppressWarnings();
@@ -849,7 +836,7 @@
// Parser may stop at some erroneous constructions like #else, #endif
// or '}' in some cases, continue parsing until we are done
parseIntoSourceFile(*NextInput, BufferID, &Done, nullptr, &PersistentState,
- DelayedCB);
+ DelayedCB, /*DelayedBodyParsing=*/!IsPrimary);
} while (!Done);
Diags.setSuppressWarnings(DidSuppressWarnings);
@@ -878,8 +865,7 @@
bool CompilerInstance::parsePartialModulesAndLibraryFiles(
const ImplicitImports &implicitImports,
PersistentParserState &PersistentState,
- DelayedParsingCallbacks *PrimaryDelayedCB,
- DelayedParsingCallbacks *SecondaryDelayedCB) {
+ DelayedParsingCallbacks *DelayedCB) {
FrontendStatsTracer tracer(Context->Stats,
"parse-partial-modules-and-library-files");
bool hadLoadError = false;
@@ -894,8 +880,7 @@
// Then parse all the library files.
for (auto BufferID : InputSourceCodeBufferIDs) {
if (BufferID != MainBufferID) {
- parseLibraryFile(BufferID, implicitImports, PersistentState,
- PrimaryDelayedCB, SecondaryDelayedCB);
+ parseLibraryFile(BufferID, implicitImports, PersistentState, DelayedCB);
}
}
return hadLoadError;
@@ -928,7 +913,7 @@
// with 'sil' definitions.
parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done,
TheSILModule ? &SILContext : nullptr, &PersistentState,
- DelayedParseCB);
+ DelayedParseCB, /*DelayedBodyParsing=*/false);
if (mainIsPrimary && (Done || CurTUElem < MainFile.Decls.size())) {
switch (LimitStage) {
@@ -1055,11 +1040,14 @@
if (BufferID == MainBufferID)
continue;
+ auto IsPrimary = isWholeModuleCompilation() || isPrimaryInput(BufferID);
+
SourceFile *NextInput = createSourceFileForMainModule(
SourceFileKind::Library, SourceFile::ImplicitModuleImportKind::None,
BufferID);
- parseIntoSourceFileFull(*NextInput, BufferID, &PersistentState);
+ parseIntoSourceFileFull(*NextInput, BufferID, &PersistentState,
+ nullptr, /*DelayBodyParsing=*/!IsPrimary);
}
// Now parse the main file.
@@ -1069,7 +1057,8 @@
MainFile.SyntaxParsingCache = Invocation.getMainFileSyntaxParsingCache();
parseIntoSourceFileFull(MainFile, MainFile.getBufferID().getValue(),
- &PersistentState);
+ &PersistentState, nullptr,
+ /*DelayBodyParsing=*/false);
}
assert(Context->LoadedModules.size() == 1 &&
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index e877ea2..bedcbc9 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1437,6 +1437,7 @@
return true;
case DeclContextKind::AbstractFunctionDecl:
case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::EnumElementDecl:
return false;
default:
continue;
diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp
index 8875737..a7cdf17 100644
--- a/lib/IDE/ExprContextAnalysis.cpp
+++ b/lib/IDE/ExprContextAnalysis.cpp
@@ -49,6 +49,7 @@
case DeclContextKind::Module:
case DeclContextKind::SerializedLocal:
case DeclContextKind::TopLevelCodeDecl:
+ case DeclContextKind::EnumElementDecl:
// Nothing to do for these.
break;
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index 879b15a..d1a4a19 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -935,6 +935,7 @@
switch (RangeInfo.RangeContext->getContextKind()) {
case swift::DeclContextKind::Initializer:
case swift::DeclContextKind::SubscriptDecl:
+ case swift::DeclContextKind::EnumElementDecl:
case swift::DeclContextKind::AbstractFunctionDecl:
case swift::DeclContextKind::AbstractClosureExpr:
case swift::DeclContextKind::TopLevelCodeDecl:
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index 67ae131..0e8877f 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -1867,6 +1867,7 @@
llvm::raw_svector_ostream outs(out);
auto propTy = prop->getValueInterfaceType();
+ auto propDC = prop->getDeclContext();
// Emit the type encoding for the property.
outs << 'T';
@@ -1884,13 +1885,13 @@
if (prop->getAttrs().hasAttribute<NSManagedAttr>())
outs << ",D";
- auto isObject = prop->getDeclContext()->mapTypeIntoContext(propTy)
+ auto isObject = propDC->mapTypeIntoContext(propTy)
->hasRetainablePointerRepresentation();
auto hasObjectEncoding = typeEnc[0] == '@';
// Determine the assignment semantics.
// Get-only properties are (readonly).
- if (!prop->isSettable(prop->getDeclContext()))
+ if (!prop->isSettable(propDC))
outs << ",R";
// Weak and Unowned properties are (weak).
else if (prop->getAttrs().hasAttribute<ReferenceOwnershipAttr>())
@@ -1908,9 +1909,12 @@
else
(void)0;
- // If the property is an instance property and has storage, emit the ivar
- // name last.
- if (!prop->isStatic() && prop->hasStorage())
+ // If the property is an instance property and has storage, and meanwhile
+ // its type is trivially representable in ObjC, emit the ivar name last.
+ bool isTriviallyRepresentable =
+ propTy->isTriviallyRepresentableIn(ForeignLanguage::ObjectiveC,
+ propDC);
+ if (!prop->isStatic() && prop->hasStorage() && isTriviallyRepresentable)
outs << ",V" << prop->getName();
}
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index c3cbe27..9a5c9b4 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -771,6 +771,7 @@
case DeclContextKind::AbstractClosureExpr:
case DeclContextKind::AbstractFunctionDecl:
case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::EnumElementDecl:
case DeclContextKind::TopLevelCodeDecl:
case DeclContextKind::Initializer:
case DeclContextKind::SerializedLocal:
@@ -984,7 +985,7 @@
return f.getProfiler() && m.getOptions().EmitProfileCoverageMapping;
}
-void IRGenerator::emitGlobalTopLevel(bool emitForParallelEmission) {
+void IRGenerator::emitGlobalTopLevel() {
// Generate order numbers for the functions in the SIL module that
// correspond to definitions in the LLVM module.
unsigned nextOrderNumber = 0;
@@ -995,10 +996,14 @@
}
// Ensure that relative symbols are collocated in the same LLVM module.
- for (SILWitnessTable &wt : PrimaryIGM->getSILModule().getWitnessTableList()) {
+ for (auto &wt : PrimaryIGM->getSILModule().getWitnessTableList()) {
CurrentIGMPtr IGM = getGenModule(wt.getDeclContext());
- if (emitForParallelEmission)
- IGM->ensureRelativeSymbolCollocation(wt);
+ ensureRelativeSymbolCollocation(wt);
+ }
+
+ for (auto &wt : PrimaryIGM->getSILModule().getDefaultWitnessTableList()) {
+ CurrentIGMPtr IGM = getGenModule(wt.getProtocol()->getDeclContext());
+ ensureRelativeSymbolCollocation(wt);
}
for (SILGlobalVariable &v : PrimaryIGM->getSILModule().getSILGlobals()) {
@@ -1903,6 +1908,8 @@
/// Add a zero initializer.
if (forDefinition)
gvar->setInitializer(llvm::Constant::getNullValue(storageTypeWithContainer));
+ else
+ gvar->setComdat(nullptr);
}
llvm::Constant *addr = gvar;
if (var->isInitializedObject()) {
@@ -2184,8 +2191,11 @@
// associated with it. The combination of the two allows us to identify the
// @_silgen_name functions. These are locally defined function thunks used in
// the standard library. Do not give them DLLImport DLL Storage.
- if (useDllStorage() && f->hasCReferences() && !forDefinition)
- fn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ if (!forDefinition) {
+ fn->setComdat(nullptr);
+ if (f->hasCReferences())
+ fn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ }
// If we have an order number for this function, set it up as appropriate.
if (hasOrderNumber) {
diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp
index 0a5244c..b6f173e 100644
--- a/lib/IRGen/GenFunc.cpp
+++ b/lib/IRGen/GenFunc.cpp
@@ -1254,7 +1254,7 @@
/// Emit a partial application thunk for a function pointer applied to a partial
/// set of argument values.
-void irgen::emitFunctionPartialApplication(
+Optional<StackAddress> irgen::emitFunctionPartialApplication(
IRGenFunction &IGF, SILFunction &SILFn, const FunctionPointer &fn,
llvm::Value *fnContext, Explosion &args, ArrayRef<SILParameterInfo> params,
SubstitutionMap subs, CanSILFunctionType origType,
@@ -1270,8 +1270,6 @@
SmallVector<SILType, 4> argValTypes;
SmallVector<ParameterConvention, 4> argConventions;
- assert(!outType->isNoEscape());
-
// Reserve space for polymorphic bindings.
auto bindings = NecessaryBindings::forFunctionInvocations(IGF.IGM,
origType, subs);
@@ -1398,7 +1396,7 @@
llvm::Value *ctx = args.claimNext();
ctx = IGF.Builder.CreateBitCast(ctx, IGF.IGM.RefCountedPtrTy);
out.add(ctx);
- return;
+ return {};
}
Optional<FunctionPointer> staticFn;
@@ -1437,14 +1435,20 @@
llvm::Value *ctx = args.claimNext();
if (isIndirectFormalParameter(*singleRefcountedConvention))
ctx = IGF.Builder.CreateLoad(ctx, IGF.IGM.getPointerAlignment());
+
+ auto expectedClosureTy =
+ outType->isNoEscape() ? IGF.IGM.OpaquePtrTy : IGF.IGM.RefCountedPtrTy;
+
// We might get a struct containing a pointer e.g type <{ %AClass* }>
- if (ctx->getType() != IGF.IGM.RefCountedPtrTy)
- ctx = IGF.coerceValue(ctx, IGF.IGM.RefCountedPtrTy, IGF.IGM.DataLayout);
+ if (ctx->getType() != expectedClosureTy)
+ ctx = IGF.coerceValue(ctx, expectedClosureTy, IGF.IGM.DataLayout);
out.add(ctx);
- return;
+ if (outType->isNoEscape())
+ return StackAddress();
+ return {};
}
- // Store the context arguments on the heap.
+ // Store the context arguments on the heap/stack.
assert(argValTypes.size() == argTypeInfos.size()
&& argTypeInfos.size() == argConventions.size()
&& "argument info lists out of sync");
@@ -1457,13 +1461,26 @@
layout);
llvm::Value *data;
- if (args.empty() && layout.isKnownEmpty()) {
- data = IGF.IGM.RefCountedNull;
- } else {
- // Allocate a new object.
- HeapNonFixedOffsets offsets(IGF, layout);
- data = IGF.emitUnmanagedAlloc(layout, "closure", descriptor, &offsets);
+ Optional<StackAddress> stackAddr;
+
+ if (args.empty() && layout.isKnownEmpty()) {
+ if (outType->isNoEscape())
+ data = llvm::ConstantPointerNull::get(IGF.IGM.OpaquePtrTy);
+ else
+ data = IGF.IGM.RefCountedNull;
+ } else {
+
+ // Allocate a new object on the heap or stack.
+ HeapNonFixedOffsets offsets(IGF, layout);
+ if (outType->isNoEscape()) {
+ stackAddr = IGF.emitDynamicAlloca(
+ IGF.IGM.Int8Ty, layout.emitSize(IGF.IGM), Alignment(16));
+ stackAddr = stackAddr->withAddress(IGF.Builder.CreateBitCast(
+ stackAddr->getAddress(), IGF.IGM.OpaquePtrTy));
+ data = stackAddr->getAddress().getAddress();
+ } else
+ data = IGF.emitUnmanagedAlloc(layout, "closure", descriptor, &offsets);
Address dataAddr = layout.emitCastTo(IGF, data);
unsigned i = 0;
@@ -1531,6 +1548,7 @@
forwarder = IGF.Builder.CreateBitCast(forwarder, IGF.IGM.Int8PtrTy);
out.add(forwarder);
out.add(data);
+ return stackAddr;
}
/// Emit the block copy helper for a block.
diff --git a/lib/IRGen/GenFunc.h b/lib/IRGen/GenFunc.h
index 45cb6a8..04bc2e4 100644
--- a/lib/IRGen/GenFunc.h
+++ b/lib/IRGen/GenFunc.h
@@ -47,7 +47,7 @@
/// Emit a partial application thunk for a function pointer applied to a
/// partial set of argument values.
- void emitFunctionPartialApplication(
+ Optional<StackAddress> emitFunctionPartialApplication(
IRGenFunction &IGF, SILFunction &SILFn, const FunctionPointer &fnPtr,
llvm::Value *fnContext, Explosion &args,
ArrayRef<SILParameterInfo> argTypes, SubstitutionMap subs,
diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp
index c7cab4d..d4e6c5e 100644
--- a/lib/IRGen/GenOpaque.cpp
+++ b/lib/IRGen/GenOpaque.cpp
@@ -555,7 +555,10 @@
/// location before the dynamic alloca's call.
void IRGenFunction::emitDeallocateDynamicAlloca(StackAddress address) {
// In coroutines, unconditionally call llvm.coro.alloca.free.
- if (isCoroutine()) {
+ // Except if the address is invalid, this happens when this is a StackAddress
+ // for a partial_apply [stack] that did not need a context object on the
+ // stack.
+ if (isCoroutine() && address.getAddress().isValid()) {
auto allocToken = address.getExtraInfo();
assert(allocToken && "dynamic alloca in coroutine without alloc token?");
auto freeFn = llvm::Intrinsic::getDeclaration(
@@ -563,7 +566,6 @@
Builder.CreateCall(freeFn, allocToken);
return;
}
-
// Otherwise, call llvm.stackrestore if an address was saved.
auto savedSP = address.getExtraInfo();
if (savedSP == nullptr)
@@ -1444,4 +1446,4 @@
} else {
storeEnumTagSinglePayload(IGF, tag, tag, address, T, isOutlined);
}
-}
\ No newline at end of file
+}
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 01ebfd9..0d142b5 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -38,8 +38,10 @@
#include "swift/ClangImporter/ClangModule.h"
#include "swift/IRGen/Linking.h"
#include "swift/SIL/SILDeclRef.h"
+#include "swift/SIL/SILDefaultWitnessTable.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILValue.h"
+#include "swift/SIL/SILWitnessTable.h"
#include "swift/SIL/SILWitnessVisitor.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/ADT/SmallString.h"
@@ -2079,7 +2081,10 @@
setTrueConstGlobal(var);
}
-void IRGenModule::ensureRelativeSymbolCollocation(SILWitnessTable &wt) {
+void IRGenerator::ensureRelativeSymbolCollocation(SILWitnessTable &wt) {
+ if (!CurrentIGM)
+ return;
+
// Only resilient conformances use relative pointers for witness methods.
if (wt.isDeclaration() || isAvailableExternally(wt.getLinkage()) ||
!isResilientConformance(wt.getConformance()))
@@ -2090,7 +2095,20 @@
continue;
auto *witness = entry.getMethodWitness().Witness;
if (witness)
- IRGen.forceLocalEmitOfLazyFunction(witness);
+ forceLocalEmitOfLazyFunction(witness);
+ }
+}
+
+void IRGenerator::ensureRelativeSymbolCollocation(SILDefaultWitnessTable &wt) {
+ if (!CurrentIGM)
+ return;
+
+ for (auto &entry : wt.getEntries()) {
+ if (entry.getKind() != SILWitnessTable::Method)
+ continue;
+ auto *witness = entry.getMethodWitness().Witness;
+ if (witness)
+ forceLocalEmitOfLazyFunction(witness);
}
}
@@ -2234,6 +2252,10 @@
if (isAvailableExternally(wt->getLinkage()))
return;
+ // Ensure that relatively-referenced symbols for witness thunks are collocated
+ // in the same LLVM module.
+ IRGen.ensureRelativeSymbolCollocation(*wt);
+
auto conf = wt->getConformance();
PrettyStackTraceConformance _st(Context, "emitting witness table for", conf);
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 4e83b4b..1f7b541 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -964,11 +964,11 @@
}
// Emit the module contents.
- irgen.emitGlobalTopLevel(true /*emitForParallelEmission*/);
+ irgen.emitGlobalTopLevel();
for (auto *File : M->getFiles()) {
if (auto *SF = dyn_cast<SourceFile>(File)) {
- IRGenModule *IGM = irgen.getGenModule(SF);
+ CurrentIGMPtr IGM = irgen.getGenModule(SF);
IGM->emitSourceFile(*SF);
} else {
File->collectLinkLibraries([&](LinkLibrary LinkLib) {
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index 8dd90f1..478a302 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -465,6 +465,7 @@
case DeclContextKind::Initializer:
case DeclContextKind::ExtensionDecl:
case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::EnumElementDecl:
case DeclContextKind::TopLevelCodeDecl:
return getOrCreateContext(DC->getParent());
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 54761c3..4f950c2 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -93,6 +93,7 @@
class ProtocolCompositionType;
class RootProtocolConformance;
struct SILDeclRef;
+ class SILDefaultWitnessTable;
class SILGlobalVariable;
class SILModule;
class SILProperty;
@@ -311,11 +312,7 @@
/// Emit functions, variables and tables which are needed anyway, e.g. because
/// they are externally visible.
- /// If \p emitForParallelEmission is true ensures that symbols that are
- /// expressed as relative pointers are collocated in the same output module
- /// with their base symbol. For example, witness methods need to be collocated
- /// with the witness table in the same LLVM module.
- void emitGlobalTopLevel(bool emitForParallelEmission = false);
+ void emitGlobalTopLevel();
/// Emit references to each of the protocol descriptors defined in this
/// IR module.
@@ -355,6 +352,10 @@
DefaultIGMForFunction[f] = CurrentIGM;
}
+ void ensureRelativeSymbolCollocation(SILWitnessTable &wt);
+
+ void ensureRelativeSymbolCollocation(SILDefaultWitnessTable &wt);
+
void noteUseOfTypeMetadata(NominalTypeDecl *type) {
noteUseOfTypeGlobals(type, true, RequireMetadata);
}
@@ -1386,8 +1387,6 @@
void emitSharedContextDescriptor(DeclContext *dc);
- void ensureRelativeSymbolCollocation(SILWitnessTable &wt);
-
llvm::GlobalVariable *
getGlobalForDynamicallyReplaceableThunk(LinkEntity &entity, llvm::Type *type,
ForDefinition_t forDefinition);
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 5aeb617..cd81ba3 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -374,6 +374,7 @@
{
public:
llvm::DenseMap<SILValue, LoweredValue> LoweredValues;
+ llvm::DenseMap<SILValue, StackAddress> LoweredPartialApplyAllocations;
llvm::DenseMap<SILType, LoweredValue> LoweredUndefs;
/// All alloc_ref instructions which allocate the object on the stack.
@@ -2527,11 +2528,16 @@
// Create the thunk and function value.
Explosion function;
- emitFunctionPartialApplication(
+ auto closureStackAddr = emitFunctionPartialApplication(
*this, *CurSILFn, calleeFn, innerContext, llArgs, params,
i->getSubstitutionMap(), origCalleeTy, i->getSubstCalleeType(),
i->getType().castTo<SILFunctionType>(), function, false);
setLoweredExplosion(v, function);
+
+ if (closureStackAddr) {
+ assert(i->isOnStack());
+ LoweredPartialApplyAllocations[v] = *closureStackAddr;
+ }
}
void IRGenSILFunction::visitIntegerLiteralInst(swift::IntegerLiteralInst *i) {
@@ -4074,6 +4080,13 @@
}
void IRGenSILFunction::visitDeallocStackInst(swift::DeallocStackInst *i) {
+ if (auto *closure = dyn_cast<PartialApplyInst>(i->getOperand())) {
+ assert(closure->isOnStack());
+ auto stackAddr = LoweredPartialApplyAllocations[i->getOperand()];
+ emitDeallocateDynamicAlloca(stackAddr);
+ return;
+ }
+
auto allocatedType = i->getOperand()->getType();
const TypeInfo &allocatedTI = getTypeInfo(allocatedType);
StackAddress stackAddr = getLoweredStackAddress(i->getOperand());
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index c62fbbf..8841829 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -1599,14 +1599,22 @@
private:
void updateLoweredTypes(SILFunction *F);
- void recreateApplies();
- void recreateSingleApply(SILInstruction *applyInst);
- void recreateConvInstrs();
- void recreateBuiltinInstrs();
- void recreateLoadInstrs();
- void recreateUncheckedEnumDataInstrs();
- void recreateUncheckedTakeEnumDataAddrInst();
- void fixStoreToBlockStorageInstrs();
+ void recreateSingleApply(SILInstruction *applyInst,
+ SmallVectorImpl<SILInstruction *> &Delete);
+ bool recreateApply(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete);
+ bool recreateConvInstr(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete);
+ bool recreateBuiltinInstr(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete);
+ bool recreateLoadInstr(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete);
+ bool recreateUncheckedEnumDataInstr(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete);
+ bool recreateUncheckedTakeEnumDataAddrInst(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete);
+ bool fixStoreToBlockStorageInstr(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete);
private:
llvm::SetVector<SILFunction *> modFuncs;
@@ -2369,7 +2377,8 @@
return op;
}
-void LoadableByAddress::recreateSingleApply(SILInstruction *applyInst) {
+void LoadableByAddress::recreateSingleApply(
+ SILInstruction *applyInst, SmallVectorImpl<SILInstruction *> &Delete) {
auto *F = applyInst->getFunction();
IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
// Collect common info
@@ -2380,7 +2389,7 @@
// else verification will fail with wrong SubstCalleeType
auto calleInstr = site.getInstruction();
if (modApplies.remove(calleInstr)) {
- recreateSingleApply(calleInstr);
+ recreateSingleApply(calleInstr, Delete);
callee = applySite.getCallee();
}
}
@@ -2481,196 +2490,215 @@
.getAs<SILFunctionType>()
->getCalleeConvention();
- auto newApply =
- applyBuilder.createPartialApply(castedApply->getLoc(), callee,
- applySite.getSubstitutionMap(), callArgs,
- partialApplyConvention);
+ auto newApply = applyBuilder.createPartialApply(
+ castedApply->getLoc(), callee, applySite.getSubstitutionMap(), callArgs,
+ partialApplyConvention, castedApply->isOnStack());
castedApply->replaceAllUsesWith(newApply);
break;
}
default:
llvm_unreachable("Unexpected instr: unknown apply type");
}
- applyInst->getParent()->erase(applyInst);
+ Delete.push_back(applyInst);
}
-void LoadableByAddress::recreateApplies() {
- while (!modApplies.empty()) {
- auto *applyInst = modApplies.pop_back_val();
- recreateSingleApply(applyInst);
- }
+bool LoadableByAddress::recreateApply(
+ SILInstruction &I, SmallVectorImpl<SILInstruction *> &Delete) {
+ if (!modApplies.count(&I))
+ return false;
+ recreateSingleApply(&I, Delete);
+ modApplies.remove(&I);
+ return true;
}
-void LoadableByAddress::recreateLoadInstrs() {
- for (auto *loadInstr : loadInstrsOfFunc) {
- SILBuilderWithScope loadBuilder(loadInstr);
- // If this is a load of a function for which we changed the return type:
- // add UncheckedBitCast before the load
- auto loadOp = loadInstr->getOperand();
- loadOp = getOperandTypeWithCastIfNecessary(
- loadInstr, loadOp, *getIRGenModule(), loadBuilder, MapperCache);
- auto *newInstr = loadBuilder.createLoad(loadInstr->getLoc(), loadOp,
- loadInstr->getOwnershipQualifier());
- loadInstr->replaceAllUsesWith(newInstr);
- loadInstr->getParent()->erase(loadInstr);
- }
+bool LoadableByAddress::recreateLoadInstr(
+ SILInstruction &I, SmallVectorImpl<SILInstruction *> &Delete) {
+ auto *loadInstr = dyn_cast<LoadInst>(&I);
+ if (!loadInstr || !loadInstrsOfFunc.count(loadInstr))
+ return false;
+
+ SILBuilderWithScope loadBuilder(loadInstr);
+ // If this is a load of a function for which we changed the return type:
+ // add UncheckedBitCast before the load
+ auto loadOp = loadInstr->getOperand();
+ loadOp = getOperandTypeWithCastIfNecessary(
+ loadInstr, loadOp, *getIRGenModule(), loadBuilder, MapperCache);
+ auto *newInstr = loadBuilder.createLoad(loadInstr->getLoc(), loadOp,
+ loadInstr->getOwnershipQualifier());
+ loadInstr->replaceAllUsesWith(newInstr);
+ Delete.push_back(loadInstr);
+ return true;
}
-void LoadableByAddress::recreateUncheckedEnumDataInstrs() {
- for (auto *enumInstr : uncheckedEnumDataOfFunc) {
- SILBuilderWithScope enumBuilder(enumInstr);
- SILFunction *F = enumInstr->getFunction();
- IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
- SILType origType = enumInstr->getType();
- GenericEnvironment *genEnv = F->getGenericEnvironment();
- SILType newType = MapperCache.getNewSILType(genEnv, origType, *currIRMod);
- auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
- enumInstr->getElement(), F->getModule());
- SingleValueInstruction *newInstr = nullptr;
- if (newType.isAddress()) {
- newType = newType.getObjectType();
- }
- if (caseTy != newType) {
- auto *takeEnum = enumBuilder.createUncheckedEnumData(
- enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
- caseTy);
- newInstr = enumBuilder.createUncheckedBitCast(enumInstr->getLoc(),
- takeEnum, newType);
- } else {
- newInstr = enumBuilder.createUncheckedEnumData(
- enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
- newType);
- }
- enumInstr->replaceAllUsesWith(newInstr);
- enumInstr->getParent()->erase(enumInstr);
+bool LoadableByAddress::recreateUncheckedEnumDataInstr(
+ SILInstruction &I, SmallVectorImpl<SILInstruction *> &Delete) {
+ auto enumInstr = dyn_cast<UncheckedEnumDataInst>(&I);
+ if (!enumInstr || !uncheckedEnumDataOfFunc.count(enumInstr))
+ return false;
+ SILBuilderWithScope enumBuilder(enumInstr);
+ SILFunction *F = enumInstr->getFunction();
+ IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
+ SILType origType = enumInstr->getType();
+ GenericEnvironment *genEnv = F->getGenericEnvironment();
+ SILType newType = MapperCache.getNewSILType(genEnv, origType, *currIRMod);
+ auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
+ enumInstr->getElement(), F->getModule());
+ SingleValueInstruction *newInstr = nullptr;
+ if (newType.isAddress()) {
+ newType = newType.getObjectType();
}
+ if (caseTy != newType) {
+ auto *takeEnum = enumBuilder.createUncheckedEnumData(
+ enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
+ caseTy);
+ newInstr = enumBuilder.createUncheckedBitCast(enumInstr->getLoc(), takeEnum,
+ newType);
+ } else {
+ newInstr = enumBuilder.createUncheckedEnumData(
+ enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
+ newType);
+ }
+ enumInstr->replaceAllUsesWith(newInstr);
+ Delete.push_back(enumInstr);
+ return false;
}
-void LoadableByAddress::recreateUncheckedTakeEnumDataAddrInst() {
- for (auto *enumInstr : uncheckedTakeEnumDataAddrOfFunc) {
- SILBuilderWithScope enumBuilder(enumInstr);
- SILFunction *F = enumInstr->getFunction();
- IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
- SILType origType = enumInstr->getType();
- GenericEnvironment *genEnv = F->getGenericEnvironment();
- SILType newType = MapperCache.getNewSILType(genEnv, origType, *currIRMod);
- auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
- enumInstr->getElement(), F->getModule());
- SingleValueInstruction *newInstr = nullptr;
- if (caseTy != origType.getObjectType()) {
- auto *takeEnum = enumBuilder.createUncheckedTakeEnumDataAddr(
- enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
- caseTy.getAddressType());
- newInstr = enumBuilder.createUncheckedAddrCast(
- enumInstr->getLoc(), takeEnum, newType.getAddressType());
- } else {
- newInstr = enumBuilder.createUncheckedTakeEnumDataAddr(
- enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
- newType.getAddressType());
- }
- enumInstr->replaceAllUsesWith(newInstr);
- enumInstr->getParent()->erase(enumInstr);
+bool LoadableByAddress::recreateUncheckedTakeEnumDataAddrInst(
+ SILInstruction &I, SmallVectorImpl<SILInstruction *> &Delete) {
+ auto *enumInstr = dyn_cast<UncheckedTakeEnumDataAddrInst>(&I);
+ if (!enumInstr || !uncheckedTakeEnumDataAddrOfFunc.count(enumInstr))
+ return false;
+ SILBuilderWithScope enumBuilder(enumInstr);
+ SILFunction *F = enumInstr->getFunction();
+ IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
+ SILType origType = enumInstr->getType();
+ GenericEnvironment *genEnv = F->getGenericEnvironment();
+ SILType newType = MapperCache.getNewSILType(genEnv, origType, *currIRMod);
+ auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
+ enumInstr->getElement(), F->getModule());
+ SingleValueInstruction *newInstr = nullptr;
+ if (caseTy != origType.getObjectType()) {
+ auto *takeEnum = enumBuilder.createUncheckedTakeEnumDataAddr(
+ enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
+ caseTy.getAddressType());
+ newInstr = enumBuilder.createUncheckedAddrCast(
+ enumInstr->getLoc(), takeEnum, newType.getAddressType());
+ } else {
+ newInstr = enumBuilder.createUncheckedTakeEnumDataAddr(
+ enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
+ newType.getAddressType());
}
+ enumInstr->replaceAllUsesWith(newInstr);
+ Delete.push_back(enumInstr);
+ return true;
}
-void LoadableByAddress::fixStoreToBlockStorageInstrs() {
- for (auto *instr : storeToBlockStorageInstrs) {
- auto dest = instr->getDest();
- auto destBlock = cast<ProjectBlockStorageInst>(dest);
- SILType destType = destBlock->getType();
- auto src = instr->getSrc();
- SILType srcType = src->getType();
- if (destType.getObjectType() != srcType) {
- // Add cast to destType
- SILBuilderWithScope castBuilder(instr);
- auto *castInstr = castBuilder.createUncheckedBitCast(
- instr->getLoc(), src, destType.getObjectType());
- instr->setOperand(StoreInst::Src, castInstr);
- }
+bool LoadableByAddress::fixStoreToBlockStorageInstr(
+ SILInstruction &I, SmallVectorImpl<SILInstruction *> &Delete) {
+ auto *instr = dyn_cast<StoreInst>(&I);
+ if (!instr || !storeToBlockStorageInstrs.count(instr))
+ return false;
+ auto dest = instr->getDest();
+ auto destBlock = cast<ProjectBlockStorageInst>(dest);
+ SILType destType = destBlock->getType();
+ auto src = instr->getSrc();
+ SILType srcType = src->getType();
+ if (destType.getObjectType() != srcType) {
+ // Add cast to destType
+ SILBuilderWithScope castBuilder(instr);
+ auto *castInstr = castBuilder.createUncheckedBitCast(
+ instr->getLoc(), src, destType.getObjectType());
+ instr->setOperand(StoreInst::Src, castInstr);
}
+ return true;
}
-void LoadableByAddress::recreateConvInstrs() {
- for (auto *convInstr : conversionInstrs) {
- IRGenModule *currIRMod =
- getIRGenModule()->IRGen.getGenModule(convInstr->getFunction());
- SILType currSILType = convInstr->getType();
- if (auto *thinToPointer = dyn_cast<ThinFunctionToPointerInst>(convInstr)) {
- currSILType = thinToPointer->getOperand()->getType();
- }
- auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
- GenericEnvironment *genEnv =
- convInstr->getFunction()->getGenericEnvironment();
- CanSILFunctionType newFnType = MapperCache.getNewSILFunctionType(
- genEnv, currSILFunctionType, *currIRMod);
- SILType newType = SILType::getPrimitiveObjectType(newFnType);
- SILBuilderWithScope convBuilder(convInstr);
- SingleValueInstruction *newInstr = nullptr;
- switch (convInstr->getKind()) {
- case SILInstructionKind::ThinToThickFunctionInst: {
- auto instr = cast<ThinToThickFunctionInst>(convInstr);
- newInstr = convBuilder.createThinToThickFunction(
- instr->getLoc(), instr->getOperand(), newType);
- break;
- }
- case SILInstructionKind::ThinFunctionToPointerInst: {
- auto instr = cast<ThinFunctionToPointerInst>(convInstr);
- newType = MapperCache.getNewSILType(genEnv, instr->getType(),
- *getIRGenModule());
- newInstr = convBuilder.createThinFunctionToPointer(
- instr->getLoc(), instr->getOperand(), newType);
- break;
- }
- case SILInstructionKind::ConvertFunctionInst: {
- auto instr = cast<ConvertFunctionInst>(convInstr);
- newInstr = convBuilder.createConvertFunction(
- instr->getLoc(), instr->getOperand(), newType,
- instr->withoutActuallyEscaping());
- break;
- }
- case SILInstructionKind::ConvertEscapeToNoEscapeInst: {
- auto instr = cast<ConvertEscapeToNoEscapeInst>(convInstr);
- newInstr = convBuilder.createConvertEscapeToNoEscape(
- instr->getLoc(), instr->getOperand(), newType,
- instr->isLifetimeGuaranteed());
- break;
- }
- case SILInstructionKind::MarkDependenceInst: {
- auto instr = cast<MarkDependenceInst>(convInstr);
- newInstr = convBuilder.createMarkDependence(
- instr->getLoc(), instr->getValue(), instr->getBase());
- break;
- }
- default:
- llvm_unreachable("Unexpected conversion instruction");
- }
- convInstr->replaceAllUsesWith(newInstr);
- convInstr->getParent()->erase(convInstr);
+bool LoadableByAddress::recreateConvInstr(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete) {
+ auto *convInstr = dyn_cast<SingleValueInstruction>(&I);
+ if (!convInstr || !conversionInstrs.count(convInstr))
+ return false;
+ IRGenModule *currIRMod =
+ getIRGenModule()->IRGen.getGenModule(convInstr->getFunction());
+ SILType currSILType = convInstr->getType();
+ if (auto *thinToPointer = dyn_cast<ThinFunctionToPointerInst>(convInstr)) {
+ currSILType = thinToPointer->getOperand()->getType();
}
+ auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
+ GenericEnvironment *genEnv =
+ convInstr->getFunction()->getGenericEnvironment();
+ CanSILFunctionType newFnType = MapperCache.getNewSILFunctionType(
+ genEnv, currSILFunctionType, *currIRMod);
+ SILType newType = SILType::getPrimitiveObjectType(newFnType);
+ SILBuilderWithScope convBuilder(convInstr);
+ SingleValueInstruction *newInstr = nullptr;
+ switch (convInstr->getKind()) {
+ case SILInstructionKind::ThinToThickFunctionInst: {
+ auto instr = cast<ThinToThickFunctionInst>(convInstr);
+ newInstr = convBuilder.createThinToThickFunction(
+ instr->getLoc(), instr->getOperand(), newType);
+ break;
+ }
+ case SILInstructionKind::ThinFunctionToPointerInst: {
+ auto instr = cast<ThinFunctionToPointerInst>(convInstr);
+ newType =
+ MapperCache.getNewSILType(genEnv, instr->getType(), *getIRGenModule());
+ newInstr = convBuilder.createThinFunctionToPointer(
+ instr->getLoc(), instr->getOperand(), newType);
+ break;
+ }
+ case SILInstructionKind::ConvertFunctionInst: {
+ auto instr = cast<ConvertFunctionInst>(convInstr);
+ newInstr = convBuilder.createConvertFunction(
+ instr->getLoc(), instr->getOperand(), newType,
+ instr->withoutActuallyEscaping());
+ break;
+ }
+ case SILInstructionKind::ConvertEscapeToNoEscapeInst: {
+ auto instr = cast<ConvertEscapeToNoEscapeInst>(convInstr);
+ newInstr = convBuilder.createConvertEscapeToNoEscape(
+ instr->getLoc(), instr->getOperand(), newType,
+ instr->isLifetimeGuaranteed());
+ break;
+ }
+ case SILInstructionKind::MarkDependenceInst: {
+ auto instr = cast<MarkDependenceInst>(convInstr);
+ newInstr = convBuilder.createMarkDependence(
+ instr->getLoc(), instr->getValue(), instr->getBase());
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected conversion instruction");
+ }
+ convInstr->replaceAllUsesWith(newInstr);
+ Delete.push_back(convInstr);
+ return true;
}
-void LoadableByAddress::recreateBuiltinInstrs() {
- for (auto *builtinInstr : builtinInstrs) {
- auto *currIRMod =
- getIRGenModule()->IRGen.getGenModule(builtinInstr->getFunction());
- auto *F = builtinInstr->getFunction();
- GenericEnvironment *genEnv = F->getGenericEnvironment();
- auto resultTy = builtinInstr->getType();
- auto newResultTy = MapperCache.getNewSILType(genEnv, resultTy, *currIRMod);
+bool LoadableByAddress::recreateBuiltinInstr(SILInstruction &I,
+ SmallVectorImpl<SILInstruction *> &Delete) {
+ auto builtinInstr = dyn_cast<BuiltinInst>(&I);
+ if (!builtinInstr || !builtinInstrs.count(builtinInstr))
+ return false;
+ auto *currIRMod =
+ getIRGenModule()->IRGen.getGenModule(builtinInstr->getFunction());
+ auto *F = builtinInstr->getFunction();
+ GenericEnvironment *genEnv = F->getGenericEnvironment();
+ auto resultTy = builtinInstr->getType();
+ auto newResultTy = MapperCache.getNewSILType(genEnv, resultTy, *currIRMod);
- llvm::SmallVector<SILValue, 5> newArgs;
- for (auto oldArg : builtinInstr->getArguments()) {
- newArgs.push_back(oldArg);
- }
-
- SILBuilderWithScope builtinBuilder(builtinInstr);
- auto *newInstr = builtinBuilder.createBuiltin(
- builtinInstr->getLoc(), builtinInstr->getName(), newResultTy,
- builtinInstr->getSubstitutions(),
- newArgs);
- builtinInstr->replaceAllUsesWith(newInstr);
- builtinInstr->getParent()->erase(builtinInstr);
+ llvm::SmallVector<SILValue, 5> newArgs;
+ for (auto oldArg : builtinInstr->getArguments()) {
+ newArgs.push_back(oldArg);
}
+
+ SILBuilderWithScope builtinBuilder(builtinInstr);
+ auto *newInstr = builtinBuilder.createBuiltin(
+ builtinInstr->getLoc(), builtinInstr->getName(), newResultTy,
+ builtinInstr->getSubstitutions(), newArgs);
+ builtinInstr->replaceAllUsesWith(newInstr);
+ Delete.push_back(builtinInstr);
+ return true;
}
void LoadableByAddress::updateLoweredTypes(SILFunction *F) {
@@ -2817,26 +2845,31 @@
instr->getParent()->erase(instr);
}
- // Re-create all conversions for which we modified the FunctionRef
- recreateConvInstrs();
-
- // Re-create all builtins for which we modified the FunctionRef
- recreateBuiltinInstrs();
-
- // Re-create all unchecked enum data instrs of function pointers
- recreateUncheckedEnumDataInstrs();
-
- // Same for data addr
- recreateUncheckedTakeEnumDataAddrInst();
-
- // Re-create all load instrs of function pointers
- recreateLoadInstrs();
-
- // Re-create all applies that we modified in the module
- recreateApplies();
-
- // Fix all instructions that rely on block storage type
- fixStoreToBlockStorageInstrs();
+ // Recreate the instructions in topological order. Some instructions inherit
+ // their result type from their operand.
+ for (SILFunction &CurrF : *getModule()) {
+ SmallVector<SILInstruction *, 32> Delete;
+ for (SILBasicBlock &BB : CurrF) {
+ for (SILInstruction &I : BB) {
+ if (recreateConvInstr(I, Delete))
+ continue;
+ else if (recreateBuiltinInstr(I, Delete))
+ continue;
+ else if (recreateUncheckedEnumDataInstr(I, Delete))
+ continue;
+ else if (recreateUncheckedTakeEnumDataAddrInst(I, Delete))
+ continue;
+ else if (recreateLoadInstr(I, Delete))
+ continue;
+ else if (recreateApply(I, Delete))
+ continue;
+ else
+ fixStoreToBlockStorageInstr(I, Delete);
+ }
+ }
+ for (auto *Inst : Delete)
+ Inst->eraseFromParent();
+ }
// Clean up the data structs:
modFuncs.clear();
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index dcb7bdc..891579c 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -13,6 +13,7 @@
ParsedSyntaxBuilders.cpp.gyb
ParsedSyntaxNodes.cpp.gyb
ParsedSyntaxRecorder.cpp.gyb
+ ParsedTrivia.cpp
ParseExpr.cpp
ParseGeneric.cpp
ParseIfConfig.cpp
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 095ff69..5555caf 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -20,6 +20,7 @@
#include "swift/AST/Identifier.h"
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
+#include "swift/Syntax/Trivia.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -284,15 +285,15 @@
if (RetainComments == CommentRetentionMode::AttachToNextToken) {
// 'CommentLength' here is the length from the *first* comment to the
// token text (or its backtick if exist).
- auto Iter = llvm::find_if(LeadingTrivia, [](const TriviaPiece &Piece) {
- return Piece.isComment();
+ auto Iter = llvm::find_if(LeadingTrivia, [](const ParsedTriviaPiece &Piece) {
+ return isCommentTriviaKind(Piece.getKind());
});
for (auto End = LeadingTrivia.end(); Iter != End; Iter++) {
if (Iter->getKind() == TriviaKind::Backtick)
// Since Token::getCommentRange() doesn't take backtick into account,
// we cannot include length of backtick.
break;
- CommentLength += Iter->getTextLength();
+ CommentLength += Iter->getLength();
}
}
@@ -310,9 +311,9 @@
assert(TokStart[0] == '`' && "escaped identifier starts with backtick");
assert(CurPtr[-1] == '`' && "escaped identifier ends with backtick");
- LeadingTrivia.push_back(TriviaPiece::backtick());
+ LeadingTrivia.push_back(TriviaKind::Backtick, 1);
assert(TrailingTrivia.empty() && "TrailingTrivia is empty here");
- TrailingTrivia.push_back(TriviaPiece::backtick());
+ TrailingTrivia.push_back(TriviaKind::Backtick, 1);
formToken(tok::identifier, TokStart);
// If this token is at ArtificialEOF, it's forced to be tok::eof. Don't mark
@@ -2335,8 +2336,7 @@
size_t BOMLen = ContentStart - BufferStart;
assert(BOMLen == 3 && "UTF-8 BOM is 3 bytes");
// Add UTF-8 BOM to LeadingTrivia.
- auto Text = OwnedString::makeRefCounted(StringRef(CurPtr, BOMLen));
- LeadingTrivia.push_back(TriviaPiece::garbageText(Text));
+ LeadingTrivia.push_back(TriviaKind::GarbageText, BOMLen);
CurPtr += BOMLen;
}
NextToken.setAtStartOfLine(true);
@@ -2521,7 +2521,7 @@
return L.peekNextToken();
}
-void Lexer::lexTrivia(syntax::Trivia &Pieces, bool IsForTrailingTrivia) {
+void Lexer::lexTrivia(ParsedTrivia &Pieces, bool IsForTrailingTrivia) {
Restart:
const char *TriviaStart = CurPtr;
@@ -2530,30 +2530,30 @@
if (IsForTrailingTrivia)
break;
NextToken.setAtStartOfLine(true);
- Pieces.appendOrSquash(TriviaPiece::newlines(1));
+ Pieces.appendOrSquash(TriviaKind::Newline, 1);
goto Restart;
case '\r':
if (IsForTrailingTrivia)
break;
NextToken.setAtStartOfLine(true);
if (CurPtr[0] == '\n') {
- Pieces.appendOrSquash(TriviaPiece::carriageReturnLineFeeds(1));
+ Pieces.appendOrSquash(TriviaKind::CarriageReturnLineFeed, 2);
++CurPtr;
} else {
- Pieces.appendOrSquash(TriviaPiece::carriageReturns(1));
+ Pieces.appendOrSquash(TriviaKind::CarriageReturn, 1);
}
goto Restart;
case ' ':
- Pieces.appendOrSquash(TriviaPiece::spaces(1));
+ Pieces.appendOrSquash(TriviaKind::Space, 1);
goto Restart;
case '\t':
- Pieces.appendOrSquash(TriviaPiece::tabs(1));
+ Pieces.appendOrSquash(TriviaKind::Tab, 1);
goto Restart;
case '\v':
- Pieces.appendOrSquash(TriviaPiece::verticalTabs(1));
+ Pieces.appendOrSquash(TriviaKind::VerticalTab, 1);
goto Restart;
case '\f':
- Pieces.appendOrSquash(TriviaPiece::formfeeds(1));
+ Pieces.appendOrSquash(TriviaKind::Formfeed, 1);
goto Restart;
case '/':
if (IsForTrailingTrivia || isKeepingComments()) {
@@ -2565,18 +2565,16 @@
bool isDocComment = CurPtr[1] == '/';
skipSlashSlashComment(/*EatNewline=*/false);
size_t Length = CurPtr - TriviaStart;
- auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
- Pieces.push_back(isDocComment ? TriviaPiece::docLineComment(Text)
- : TriviaPiece::lineComment(Text));
+ Pieces.push_back(isDocComment ? TriviaKind::DocLineComment
+ : TriviaKind::LineComment, Length);
goto Restart;
} else if (*CurPtr == '*') {
// '/* ... */' comment.
bool isDocComment = CurPtr[1] == '*';
skipSlashStarComment();
size_t Length = CurPtr - TriviaStart;
- auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
- Pieces.push_back(isDocComment ? TriviaPiece::docBlockComment(Text)
- : TriviaPiece::blockComment(Text));
+ Pieces.push_back(isDocComment ? TriviaKind::DocBlockComment
+ : TriviaKind::BlockComment, Length);
goto Restart;
}
break;
@@ -2588,8 +2586,7 @@
diagnose(TriviaStart, diag::lex_hashbang_not_allowed);
skipHashbang(/*EatNewline=*/false);
size_t Length = CurPtr - TriviaStart;
- auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
- Pieces.push_back(TriviaPiece::garbageText(Text));
+ Pieces.push_back(TriviaKind::GarbageText, Length);
goto Restart;
}
break;
@@ -2598,8 +2595,7 @@
if (tryLexConflictMarker(/*EatNewline=*/false)) {
// Conflict marker.
size_t Length = CurPtr - TriviaStart;
- auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
- Pieces.push_back(TriviaPiece::garbageText(Text));
+ Pieces.push_back(TriviaKind::GarbageText, Length);
goto Restart;
}
break;
@@ -2608,8 +2604,7 @@
case NulCharacterKind::Embedded: {
diagnoseEmbeddedNul(Diags, CurPtr - 1);
size_t Length = CurPtr - TriviaStart;
- auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
- Pieces.push_back(TriviaPiece::garbageText(Text));
+ Pieces.push_back(TriviaKind::GarbageText, Length);
goto Restart;
}
case NulCharacterKind::CodeCompletion:
@@ -2655,8 +2650,7 @@
}
size_t Length = CurPtr - TriviaStart;
- auto Text = OwnedString::makeRefCounted(StringRef(TriviaStart, Length));
- Pieces.push_back(TriviaPiece::garbageText(Text));
+ Pieces.push_back(TriviaKind::GarbageText, Length);
goto Restart;
}
// Reset the cursor.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 1959d79..0b06391 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3045,22 +3045,13 @@
if (auto *ext = dyn_cast<ExtensionDecl>(D)) {
parseDeclList(ext->getBraces().Start, RBLoc, Id,
ParseDeclOptions(DelayedState->Flags),
- [&] (Decl *D) { ext->addMember(D); });
+ ext);
ext->setBraces({LBLoc, RBLoc});
- } else if (auto *cd = dyn_cast<ClassDecl>(D)) {
- auto handler = [&] (Decl *D) {
- cd->addMember(D);
- if (isa<DestructorDecl>(D))
- cd->setHasDestructor();
- };
- parseDeclList(cd->getBraces().Start, RBLoc, Id,
- ParseDeclOptions(DelayedState->Flags), handler);
- cd->setBraces({LBLoc, RBLoc});
} else {
auto *ntd = cast<NominalTypeDecl>(D);
parseDeclList(ntd->getBraces().Start, RBLoc, Id,
ParseDeclOptions(DelayedState->Flags),
- [&] (Decl *D) { ntd->addMember(D); });
+ ntd);
ntd->setBraces({LBLoc, RBLoc});
}
}
@@ -3477,13 +3468,14 @@
/// \endverbatim
bool Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
Diag<> ErrorDiag, ParseDeclOptions Options,
- llvm::function_ref<void(Decl*)> handler) {
+ IterableDeclContext *IDC) {
ParserStatus Status;
bool PreviousHadSemi = true;
{
SyntaxParsingContext ListContext(SyntaxContext, SyntaxKind::MemberDeclList);
while (Tok.isNot(tok::r_brace)) {
- Status |= parseDeclItem(PreviousHadSemi, Options, handler);
+ Status |= parseDeclItem(PreviousHadSemi, Options,
+ [&](Decl *D) { IDC->addMember(D); });
if (Tok.isAny(tok::eof, tok::pound_endif, tok::pound_else,
tok::pound_elseif)) {
IsInputIncomplete = true;
@@ -3504,30 +3496,15 @@
bool Parser::canDelayMemberDeclParsing() {
// If explicitly disabled, respect the flag.
- if (DisableDelayedParsing)
+ if (!DelayBodyParsing)
return false;
- // There's no fundamental reasons that SIL cannnot be lasily parsed. We need
- // to keep SILParserTUStateBase persistent to make it happen.
- if (isInSILMode())
- return false;
- // Calculating interface hash requires tokens consumed in the original order.
- if (SF.hasInterfaceHash())
- return false;
- if (SF.Kind == SourceFileKind::REPL)
- return false;
- // We always collect the entire syntax tree for IDE uses.
- if (SF.shouldCollectToken())
- return false;
- if (SF.shouldBuildSyntaxTree())
- return false;
- // Recovering parser status later for #sourceLocaion is not-trivial and
+ // Recovering parser status later for #sourceLocation is not-trivial and
// it may not worth it.
if (InPoundLineEnvironment)
return false;
- // The first code completion pass looks for code completion tokens extensively,
- // so we cannot lazily parse members.
- if (isCodeCompletionFirstPass())
- return false;
+
+ // Skip until the matching right curly bracket; if we find a pound directive,
+ // we can't lazily parse.
BacktrackingScope BackTrack(*this);
bool HasPoundDirective;
skipUntilMatchingRBrace(*this, HasPoundDirective, SyntaxContext);
@@ -3536,6 +3513,23 @@
return !BackTrack.willBacktrack();
}
+bool Parser::delayParsingDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
+ SourceLoc PosBeforeLB,
+ ParseDeclOptions Options,
+ IterableDeclContext *IDC) {
+ bool error = false;
+
+ if (Tok.is(tok::r_brace)) {
+ RBLoc = consumeToken();
+ } else {
+ RBLoc = Tok.getLoc();
+ error = true;
+ }
+ State->delayDeclList(IDC, Options.toRaw(), CurDeclContext, { LBLoc, RBLoc },
+ PosBeforeLB);
+ return error;
+}
+
/// Parse an 'extension' declaration.
///
/// \verbatim
@@ -3600,17 +3594,11 @@
Scope S(this, ScopeKind::Extension);
ParseDeclOptions Options(PD_HasContainerType | PD_InExtension);
if (canDelayMemberDeclParsing()) {
- if (Tok.is(tok::r_brace)) {
- RBLoc = consumeToken();
- } else {
- RBLoc = Tok.getLoc();
+ if (delayParsingDeclList(LBLoc, RBLoc, PosBeforeLB, Options, ext))
status.setIsParseError();
- }
- State->delayDeclList(ext, Options.toRaw(), CurDeclContext, { LBLoc, RBLoc },
- PosBeforeLB);
} else {
if (parseDeclList(LBLoc, RBLoc, diag::expected_rbrace_extension,
- Options, [&] (Decl *D) { ext->addMember(D); }))
+ Options, ext))
status.setIsParseError();
}
@@ -5395,7 +5383,8 @@
BodyRange.End = PreviousLoc;
- if (DelayedParseCB->shouldDelayFunctionBodyParsing(*this, AFD, Attrs,
+ if (DelayedParseCB &&
+ DelayedParseCB->shouldDelayFunctionBodyParsing(*this, AFD, Attrs,
BodyRange)) {
State->delayFunctionBodyParsing(AFD, BodyRange,
BeginParserPosition.PreviousLoc);
@@ -5737,20 +5726,14 @@
RBLoc = LBLoc;
Status.setIsParseError();
} else {
- Scope S(this, ScopeKind::ClassBody);
+ Scope S(this, ScopeKind::EnumBody);
ParseDeclOptions Options(PD_HasContainerType | PD_AllowEnumElement | PD_InEnum);
if (canDelayMemberDeclParsing()) {
- if (Tok.is(tok::r_brace)) {
- RBLoc = consumeToken();
- } else {
- RBLoc = Tok.getLoc();
+ if (delayParsingDeclList(LBLoc, RBLoc, PosBeforeLB, Options, ED))
Status.setIsParseError();
- }
- State->delayDeclList(ED, Options.toRaw(), CurDeclContext, { LBLoc, RBLoc },
- PosBeforeLB);
} else {
if (parseDeclList(LBLoc, RBLoc, diag::expected_rbrace_enum,
- Options, [&] (Decl *D) { ED->addMember(D); }))
+ Options, ED))
Status.setIsParseError();
}
}
@@ -6025,17 +6008,11 @@
Scope S(this, ScopeKind::StructBody);
ParseDeclOptions Options(PD_HasContainerType | PD_InStruct);
if (canDelayMemberDeclParsing()) {
- if (Tok.is(tok::r_brace)) {
- RBLoc = consumeToken();
- } else {
- RBLoc = Tok.getLoc();
+ if (delayParsingDeclList(LBLoc, RBLoc, PosBeforeLB, Options, SD))
Status.setIsParseError();
- }
- State->delayDeclList(SD, Options.toRaw(), CurDeclContext, { LBLoc, RBLoc },
- PosBeforeLB);
} else {
if (parseDeclList(LBLoc, RBLoc, diag::expected_rbrace_struct,
- Options, [&](Decl *D) {SD->addMember(D);}))
+ Options,SD))
Status.setIsParseError();
}
}
@@ -6149,22 +6126,11 @@
ParseDeclOptions Options(PD_HasContainerType | PD_AllowDestructor |
PD_InClass);
if (canDelayMemberDeclParsing()) {
- if (Tok.is(tok::r_brace)) {
- RBLoc = consumeToken();
- } else {
- RBLoc = Tok.getLoc();
+ if (delayParsingDeclList(LBLoc, RBLoc, PosBeforeLB, Options, CD))
Status.setIsParseError();
- }
- State->delayDeclList(CD, Options.toRaw(), CurDeclContext, { LBLoc, RBLoc },
- PosBeforeLB);
} else {
- auto Handler = [&] (Decl *D) {
- CD->addMember(D);
- if (isa<DestructorDecl>(D))
- CD->setHasDestructor();
- };
if (parseDeclList(LBLoc, RBLoc, diag::expected_rbrace_class,
- Options, Handler))
+ Options, CD))
Status.setIsParseError();
}
}
@@ -6259,18 +6225,11 @@
PD_DisallowInit |
PD_InProtocol);
if (canDelayMemberDeclParsing()) {
- if (Tok.is(tok::r_brace)) {
- RBraceLoc = consumeToken();
- } else {
- RBraceLoc = Tok.getLoc();
+ if (delayParsingDeclList(LBraceLoc, RBraceLoc, PosBeforeLB, Options, Proto))
Status.setIsParseError();
- }
- State->delayDeclList(Proto, Options.toRaw(), CurDeclContext,
- { LBraceLoc, RBraceLoc },
- PosBeforeLB);
} else {
if (parseDeclList(LBraceLoc, RBraceLoc, diag::expected_rbrace_protocol,
- Options, [&](Decl *D) {Proto->addMember(D);}))
+ Options, Proto))
Status.setIsParseError();
}
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index fd3293a..81025e0 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1165,7 +1165,7 @@
Result = makeParserResult(
Result,
new (Context) DotSelfExpr(Result.get(), TokLoc, consumeToken()));
- SyntaxContext->createNodeInPlace(SyntaxKind::DotSelfExpr);
+ SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);
continue;
}
@@ -1560,7 +1560,8 @@
ParsedSyntaxRecorder::makeIdentifierPattern(
SyntaxContext->popToken(), *SyntaxContext);
ParsedExprSyntax ExprNode =
- ParsedSyntaxRecorder::deferUnresolvedPatternExpr(PatternNode);
+ ParsedSyntaxRecorder::deferUnresolvedPatternExpr(PatternNode,
+ *SyntaxContext);
SyntaxContext->addSyntax(ExprNode);
}
return makeParserResult(new (Context) UnresolvedPatternExpr(pattern));
@@ -1635,7 +1636,7 @@
Name = parseUnqualifiedDeclName(/*afterDot=*/true, NameLoc,
diag::expected_identifier_after_dot_expr);
if (!Name) return nullptr;
- SyntaxContext->createNodeInPlace(SyntaxKind::ImplicitMemberExpr);
+ SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);
// Check for a () suffix, which indicates a call when constructing
// this member. Note that this cannot be the start of a new line.
@@ -1801,7 +1802,7 @@
unsigned &InterpolationCount) {
SourceLoc Loc = EntireTok.getLoc();
ParserStatus Status;
- Trivia EmptyTrivia;
+ ParsedTrivia EmptyTrivia;
bool First = true;
DeclName appendLiteral(Context, Context.Id_appendLiteral, { Identifier() });
@@ -2027,8 +2028,8 @@
// Make unknown tokens to represent the open and close quote.
Token OpenQuote(QuoteKind, OpenQuoteStr);
Token CloseQuote(QuoteKind, CloseQuoteStr);
- Trivia EmptyTrivia;
- Trivia EntireTrailingTrivia = TrailingTrivia;
+ ParsedTrivia EmptyTrivia;
+ ParsedTrivia EntireTrailingTrivia = TrailingTrivia;
// Add the open quote to the context; the quote should have the leading trivia
// of the entire string token and a void trailing trivia.
@@ -2040,8 +2041,8 @@
// We are going to mess with Tok to do reparsing for interpolated literals,
// don't lose our 'next' token.
llvm::SaveAndRestore<Token> SavedTok(Tok);
- llvm::SaveAndRestore<Trivia> SavedLeadingTrivia(LeadingTrivia);
- llvm::SaveAndRestore<Trivia> SavedTrailingTrivia(TrailingTrivia);
+ llvm::SaveAndRestore<ParsedTrivia> SavedLeadingTrivia(LeadingTrivia);
+ llvm::SaveAndRestore<ParsedTrivia> SavedTrailingTrivia(TrailingTrivia);
// We're not in a place where an interpolation would be valid.
if (!CurLocalContext) {
diff --git a/lib/Parse/ParsedRawSyntaxNode.cpp b/lib/Parse/ParsedRawSyntaxNode.cpp
index dc81ec9..c281260 100644
--- a/lib/Parse/ParsedRawSyntaxNode.cpp
+++ b/lib/Parse/ParsedRawSyntaxNode.cpp
@@ -11,18 +11,43 @@
//===----------------------------------------------------------------------===//
#include "swift/Parse/ParsedRawSyntaxNode.h"
+#include "swift/Parse/SyntaxParsingContext.h"
using namespace swift;
using namespace swift::syntax;
+using namespace llvm;
ParsedRawSyntaxNode
-ParsedRawSyntaxNode::makeDeferredMissing(tok kind, SourceLoc loc) {
- // Pass appropriate text for the missing token to have the provided location
- // but zero length.
- StringRef tokText = CharSourceRange{loc, 0}.str();
- auto raw = ParsedRawSyntaxNode::makeDeferred(Token{kind, tokText}, {}, {});
- raw.IsMissing = true;
- return raw;
+ParsedRawSyntaxNode::makeDeferred(SyntaxKind k,
+ ArrayRef<ParsedRawSyntaxNode> deferredNodes,
+ SyntaxParsingContext &ctx) {
+ if (deferredNodes.empty()) {
+ return ParsedRawSyntaxNode(k, {});
+ }
+ ParsedRawSyntaxNode *newPtr =
+ ctx.getScratchAlloc().Allocate<ParsedRawSyntaxNode>(deferredNodes.size());
+ std::uninitialized_copy(deferredNodes.begin(), deferredNodes.end(), newPtr);
+ return ParsedRawSyntaxNode(k, makeArrayRef(newPtr, deferredNodes.size()));
+}
+
+ParsedRawSyntaxNode
+ParsedRawSyntaxNode::makeDeferred(Token tok,
+ const ParsedTrivia &leadingTrivia,
+ const ParsedTrivia &trailingTrivia,
+ SyntaxParsingContext &ctx) {
+ CharSourceRange tokRange = tok.getRangeWithoutBackticks();
+ size_t piecesCount = leadingTrivia.size() + trailingTrivia.size();
+ ParsedTriviaPiece *piecesPtr = nullptr;
+ if (piecesCount > 0) {
+ piecesPtr = ctx.getScratchAlloc().Allocate<ParsedTriviaPiece>(piecesCount);
+ std::uninitialized_copy(leadingTrivia.begin(), leadingTrivia.end(),
+ piecesPtr);
+ std::uninitialized_copy(trailingTrivia.begin(), trailingTrivia.end(),
+ piecesPtr + leadingTrivia.size());
+ }
+ return ParsedRawSyntaxNode(tok.getKind(), tokRange.getStart(),
+ tokRange.getByteLength(), piecesPtr,
+ leadingTrivia.size(), trailingTrivia.size());
}
void ParsedRawSyntaxNode::dump() const {
diff --git a/lib/Parse/ParsedRawSyntaxRecorder.cpp b/lib/Parse/ParsedRawSyntaxRecorder.cpp
index 184906c..41f3db8 100644
--- a/lib/Parse/ParsedRawSyntaxRecorder.cpp
+++ b/lib/Parse/ParsedRawSyntaxRecorder.cpp
@@ -18,33 +18,35 @@
#include "swift/Parse/ParsedRawSyntaxRecorder.h"
#include "swift/Parse/ParsedRawSyntaxNode.h"
+#include "swift/Parse/ParsedTrivia.h"
#include "swift/Parse/SyntaxParseActions.h"
#include "swift/Parse/Token.h"
#include "swift/Syntax/SyntaxKind.h"
-#include "swift/Syntax/Trivia.h"
using namespace swift;
using namespace swift::syntax;
ParsedRawSyntaxNode
ParsedRawSyntaxRecorder::recordToken(const Token &tok,
- const Trivia &leadingTrivia,
- const Trivia &trailingTrivia) {
- SourceLoc tokLoc = tok.getLoc();
- unsigned tokLength = tok.getLength();
- if (tok.isEscapedIdentifier()) {
- // Adjust to account for the backticks that are included in trivia.
- tokLoc = tokLoc.getAdvancedLoc(1);
- tokLength -= 2;
- }
- unsigned leadingTriviaLen = leadingTrivia.getTextLength();
- unsigned trailingTriviaLen = trailingTrivia.getTextLength();
- SourceLoc offset = tokLoc.getAdvancedLoc(-leadingTriviaLen);
- unsigned length = leadingTriviaLen + tokLength + trailingTriviaLen;
+ const ParsedTrivia &leadingTrivia,
+ const ParsedTrivia &trailingTrivia) {
+ return recordToken(tok.getKind(), tok.getRangeWithoutBackticks(),
+ leadingTrivia.Pieces, trailingTrivia.Pieces);
+}
+
+ParsedRawSyntaxNode
+ParsedRawSyntaxRecorder::recordToken(tok tokKind, CharSourceRange tokRange,
+ ArrayRef<ParsedTriviaPiece> leadingTrivia,
+ ArrayRef<ParsedTriviaPiece> trailingTrivia) {
+ size_t leadingTriviaLen = ParsedTriviaPiece::getTotalLength(leadingTrivia);
+ size_t trailingTriviaLen = ParsedTriviaPiece::getTotalLength(trailingTrivia);
+ SourceLoc offset = tokRange.getStart().getAdvancedLoc(-leadingTriviaLen);
+ unsigned length = leadingTriviaLen + tokRange.getByteLength() +
+ trailingTriviaLen;
CharSourceRange range{offset, length};
- OpaqueSyntaxNode n = SPActions->recordToken(tok, leadingTrivia,
+ OpaqueSyntaxNode n = SPActions->recordToken(tokKind, leadingTrivia,
trailingTrivia, range);
- return ParsedRawSyntaxNode{SyntaxKind::Token, tok.getKind(), range, n};
+ return ParsedRawSyntaxNode{SyntaxKind::Token, tokKind, range, n};
}
ParsedRawSyntaxNode
@@ -61,11 +63,13 @@
if (node.isDeferredLayout())
return rec.recordRawSyntax(node.getKind(), node.getDeferredChildren());
assert(node.isDeferredToken());
- const Token &tok = node.getToken();
+ CharSourceRange tokRange = node.getDeferredTokenRangeWithoutBackticks();
+ tok tokKind = node.getTokenKind();
if (node.isMissing())
- return rec.recordMissingToken(tok.getKind(), tok.getLoc());
- return rec.recordToken(tok, node.getLeadingTrivia(),
- node.getTrailingTrivia());
+ return rec.recordMissingToken(tokKind, tokRange.getStart());
+ return rec.recordToken(tokKind,tokRange,
+ node.getDeferredLeadingTriviaPieces(),
+ node.getDeferredTrailingTriviaPieces());
}
ParsedRawSyntaxNode
diff --git a/lib/Parse/ParsedSyntaxBuilders.cpp.gyb b/lib/Parse/ParsedSyntaxBuilders.cpp.gyb
index 0113cbb..8e40cba 100644
--- a/lib/Parse/ParsedSyntaxBuilders.cpp.gyb
+++ b/lib/Parse/ParsedSyntaxBuilders.cpp.gyb
@@ -29,24 +29,27 @@
% for node in SYNTAX_NODES:
% if node.is_buildable():
% for child in node.children:
-Parsed${node.name}Builder &
-Parsed${node.name}Builder::use${child.name}(Parsed${child.type_name} ${child.name}) {
- Layout[cursorIndex(${node.name}::Cursor::${child.name})] =
- ${child.name}.getRaw();
- return *this;
-}
+% child_elt = None
+% child_elt_type = None
% child_node = NODE_MAP.get(child.syntax_kind)
% if child_node and child_node.is_syntax_collection():
% child_elt = child_node.collection_element_name
% child_elt_type = child_node.collection_element_type
+% end
+Parsed${node.name}Builder &
+Parsed${node.name}Builder::use${child.name}(Parsed${child.type_name} ${child.name}) {
+% if child_elt:
+ assert(${child_elt}Nodes.empty() && "use either 'use' function or 'add', not both");
+% end
+ Layout[cursorIndex(${node.name}::Cursor::${child.name})] =
+ ${child.name}.getRaw();
+ return *this;
+}
+% if child_elt:
Parsed${node.name}Builder &
Parsed${node.name}Builder::add${child_elt}(Parsed${child_elt_type} ${child_elt}) {
- auto &raw = Layout[cursorIndex(${node.name}::Cursor::${child.name})];
- if (raw.isNull())
- raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${child_node.syntax_kind},
- {${child_elt}.getRaw()});
- else
- raw.addDeferredChild(${child_elt}.getRaw());
+ assert(Layout[cursorIndex(${node.name}::Cursor::${child.name})].isNull() && "use either 'use' function or 'add', not both");
+ ${child_elt}Nodes.push_back(std::move(${child_elt}.getRaw()));
return *this;
}
% end
@@ -54,39 +57,62 @@
Parsed${node.name}
Parsed${node.name}Builder::record() {
- finishLayout();
+ finishLayout(/*deferred=*/false);
+ auto &Rec = SPCtx.getRecorder();
auto raw = Rec.recordRawSyntax(SyntaxKind::${node.syntax_kind}, Layout);
return Parsed${node.name}(std::move(raw));
}
Parsed${node.name}
Parsed${node.name}Builder::makeDeferred() {
- finishLayout();
+ finishLayout(/*deferred=*/true);
auto raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind},
- Layout);
+ Layout, SPCtx);
return Parsed${node.name}(std::move(raw));
}
Parsed${node.name}
Parsed${node.name}Builder::build() {
- if (IsBacktracking)
+ if (SPCtx.isBacktracking())
return makeDeferred();
return record();
}
-void Parsed${node.name}Builder::finishLayout() {
+void Parsed${node.name}Builder::finishLayout(bool deferred) {
+ auto &Rec = SPCtx.getRecorder();
+ (void)Rec;
% if node.children:
% for (idx, child) in enumerate(node.children):
+% child_elt = None
+% child_node = NODE_MAP.get(child.syntax_kind)
+% if child_node and child_node.is_syntax_collection():
+% child_elt = child_node.collection_element_name
+% if child_elt:
+ if (!${child_elt}Nodes.empty()) {
+ if (deferred) {
+ Layout[${idx}] = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${child_node.syntax_kind},
+ ${child_elt}Nodes, SPCtx);
+ } else {
+ Layout[${idx}] = Rec.recordRawSyntax(SyntaxKind::${child_node.syntax_kind}, ${child_elt}Nodes);
+ }
+ }
+% end
% if not child.is_optional:
if (Layout[${idx}].isNull()) {
% if child.is_token():
% token = child.main_token()
% tok_kind = token.kind if token else "unknown"
- if (IsBacktracking) {
+ if (deferred) {
Layout[${idx}] = ParsedRawSyntaxNode::makeDeferredMissing(tok::${tok_kind}, SourceLoc());
} else {
Layout[${idx}] = Rec.recordMissingToken(tok::${tok_kind}, SourceLoc());
}
+% elif child_elt:
+ if (deferred) {
+ Layout[${idx}] = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${child_node.syntax_kind}, {}, SPCtx);
+ } else {
+ Layout[${idx}] = Rec.recordRawSyntax(SyntaxKind::${child_node.syntax_kind}, {});
+ }
% else:
llvm_unreachable("need missing non-token nodes ?");
% end
diff --git a/lib/Parse/ParsedSyntaxRecorder.cpp.gyb b/lib/Parse/ParsedSyntaxRecorder.cpp.gyb
index d504ed9..17700cc 100644
--- a/lib/Parse/ParsedSyntaxRecorder.cpp.gyb
+++ b/lib/Parse/ParsedSyntaxRecorder.cpp.gyb
@@ -98,7 +98,7 @@
}
Parsed${node.name}
-ParsedSyntaxRecorder::defer${node.syntax_kind}(${child_params}) {
+ParsedSyntaxRecorder::defer${node.syntax_kind}(${child_params}, SyntaxParsingContext &SPCtx) {
auto raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind}, {
% for child in node.children:
% if child.is_optional:
@@ -107,7 +107,7 @@
${child.name}.getRaw(),
% end
% end
- });
+ }, SPCtx);
return Parsed${node.name}(std::move(raw));
}
@@ -115,7 +115,7 @@
ParsedSyntaxRecorder::make${node.syntax_kind}(${child_params},
SyntaxParsingContext &SPCtx) {
if (SPCtx.isBacktracking())
- return defer${node.syntax_kind}(${child_move_args});
+ return defer${node.syntax_kind}(${child_move_args}, SPCtx);
return record${node.syntax_kind}(${child_move_args}, SPCtx.getRecorder());
}
@@ -135,14 +135,15 @@
Parsed${node.name}
ParsedSyntaxRecorder::defer${node.syntax_kind}(
- ArrayRef<Parsed${node.collection_element_type}> elements) {
+ ArrayRef<Parsed${node.collection_element_type}> elements,
+ SyntaxParsingContext &SPCtx) {
SmallVector<ParsedRawSyntaxNode, 16> layout;
layout.reserve(elements.size());
for (auto &element : elements) {
layout.push_back(element.getRaw());
}
auto raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind},
- layout);
+ layout, SPCtx);
return Parsed${node.name}(std::move(raw));
}
@@ -151,7 +152,7 @@
ArrayRef<Parsed${node.collection_element_type}> elements,
SyntaxParsingContext &SPCtx) {
if (SPCtx.isBacktracking())
- return defer${node.syntax_kind}(elements);
+ return defer${node.syntax_kind}(elements, SPCtx);
return record${node.syntax_kind}(elements, SPCtx.getRecorder());
}
@@ -161,7 +162,7 @@
ParsedRawSyntaxNode raw;
if (SPCtx.isBacktracking()) {
// FIXME: 'loc' is not preserved when capturing a deferred layout.
- raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind}, {});
+ raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind}, {}, SPCtx);
} else {
raw = SPCtx.getRecorder().recordEmptyRawSyntaxCollection(SyntaxKind::${node.syntax_kind}, loc);
}
diff --git a/lib/Parse/ParsedTrivia.cpp b/lib/Parse/ParsedTrivia.cpp
new file mode 100644
index 0000000..7064ba2
--- /dev/null
+++ b/lib/Parse/ParsedTrivia.cpp
@@ -0,0 +1,40 @@
+//===--- ParsedTrivia.cpp - ParsedTrivia API ----------------------------*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/Parse/ParsedTrivia.h"
+#include "swift/Syntax/Trivia.h"
+#include "swift/Basic/SourceManager.h"
+
+using namespace swift;
+using namespace swift::syntax;
+
+Trivia
+ParsedTriviaPiece::convertToSyntaxTrivia(ArrayRef<ParsedTriviaPiece> pieces,
+ SourceLoc loc,
+ const SourceManager &SM,
+ unsigned bufferID) {
+ Trivia trivia;
+ SourceLoc curLoc = loc;
+ for (const auto &piece : pieces) {
+ CharSourceRange range{curLoc, piece.getLength()};
+ StringRef text = SM.extractText(range, bufferID);
+ trivia.push_back(TriviaPiece::fromText(piece.getKind(), text));
+ curLoc = curLoc.getAdvancedLoc(piece.getLength());
+ }
+ return trivia;
+}
+
+Trivia
+ParsedTrivia::convertToSyntaxTrivia(SourceLoc loc, const SourceManager &SM,
+ unsigned bufferID) const {
+ return ParsedTriviaPiece::convertToSyntaxTrivia(Pieces, loc, SM, bufferID);
+}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index b3988bb..afb476c 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -73,7 +73,7 @@
}
Token Tok;
- syntax::Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
do {
L.lex(Tok, LeadingTrivia, TrailingTrivia);
@@ -83,7 +83,7 @@
if (F != ResetTokens.end()) {
assert(F->isNot(tok::string_literal));
- DestFunc(*F, syntax::Trivia(), syntax::Trivia());
+ DestFunc(*F, ParsedTrivia(), ParsedTrivia());
auto NewState = L.getStateForBeginningOfTokenLoc(
F->getLoc().getAdvancedLoc(F->getLength()));
@@ -95,7 +95,7 @@
std::vector<Token> StrTokens;
getStringPartTokens(Tok, LangOpts, SM, BufferID, StrTokens);
for (auto &StrTok : StrTokens) {
- DestFunc(StrTok, syntax::Trivia(), syntax::Trivia());
+ DestFunc(StrTok, ParsedTrivia(), ParsedTrivia());
}
} else {
DestFunc(Tok, LeadingTrivia, TrailingTrivia);
@@ -139,7 +139,8 @@
SourceFile &SF = *AFD->getDeclContext()->getParentSourceFile();
SourceManager &SourceMgr = SF.getASTContext().SourceMgr;
unsigned BufferID = SourceMgr.findBufferContainingLoc(AFD->getLoc());
- Parser TheParser(BufferID, SF, nullptr, &ParserState);
+ Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr,
+ /*DelayBodyParsing=*/false);
TheParser.SyntaxContext->disable();
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion;
if (CodeCompletionFactory) {
@@ -165,7 +166,8 @@
SourceManager &SourceMgr = SF.getASTContext().SourceMgr;
unsigned BufferID =
SourceMgr.findBufferContainingLoc(ParserState.getDelayedDeclLoc());
- Parser TheParser(BufferID, SF, nullptr, &ParserState);
+ Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr,
+ /*DelayBodyParsing=*/false);
// Disable libSyntax creation in the delayed parsing.
TheParser.SyntaxContext->disable();
@@ -292,8 +294,8 @@
: CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithoutTrivia, TokenizeInterpolatedString,
SplitTokens,
- [&](const Token &Tok, const Trivia &LeadingTrivia,
- const Trivia &TrailingTrivia) { Tokens.push_back(Tok); });
+ [&](const Token &Tok, const ParsedTrivia &LeadingTrivia,
+ const ParsedTrivia &TrailingTrivia) { Tokens.push_back(Tok); });
assert(Tokens.back().is(tok::eof));
Tokens.pop_back(); // Remove EOF.
@@ -314,12 +316,22 @@
CommentRetentionMode::AttachToNextToken, TriviaRetentionMode::WithTrivia,
/*TokenizeInterpolatedString=*/false,
/*SplitTokens=*/ArrayRef<Token>(),
- [&](const Token &Tok, const Trivia &LeadingTrivia,
- const Trivia &TrailingTrivia) {
+ [&](const Token &Tok, const ParsedTrivia &LeadingTrivia,
+ const ParsedTrivia &TrailingTrivia) {
+ CharSourceRange TokRange = Tok.getRangeWithoutBackticks();
+ SourceLoc LeadingTriviaLoc =
+ TokRange.getStart().getAdvancedLoc(-LeadingTrivia.getLength());
+ SourceLoc TrailingTriviaLoc =
+ TokRange.getStart().getAdvancedLoc(TokRange.getByteLength());
+ Trivia syntaxLeadingTrivia =
+ LeadingTrivia.convertToSyntaxTrivia(LeadingTriviaLoc, SM, BufferID);
+ Trivia syntaxTrailingTrivia =
+ TrailingTrivia.convertToSyntaxTrivia(TrailingTriviaLoc, SM, BufferID);
auto Text = OwnedString::makeRefCounted(Tok.getText());
auto ThisToken =
- RawSyntax::make(Tok.getKind(), Text, LeadingTrivia.Pieces,
- TrailingTrivia.Pieces, SourcePresence::Present);
+ RawSyntax::make(Tok.getKind(), Text, syntaxLeadingTrivia.Pieces,
+ syntaxTrailingTrivia.Pieces,
+ SourcePresence::Present);
auto ThisTokenPos = ThisToken->accumulateAbsolutePosition(RunningPos);
Tokens.push_back({ThisToken, ThisTokenPos.getValue()});
@@ -336,15 +348,15 @@
Parser::Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
PersistentParserState *PersistentState,
std::shared_ptr<SyntaxParseActions> SPActions,
- bool DisableDelayedParsing)
+ bool DelayBodyParsing)
: Parser(BufferID, SF, &SF.getASTContext().Diags, SIL, PersistentState,
- std::move(SPActions), DisableDelayedParsing) {}
+ std::move(SPActions), DelayBodyParsing) {}
Parser::Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags,
SILParserTUStateBase *SIL,
PersistentParserState *PersistentState,
std::shared_ptr<SyntaxParseActions> SPActions,
- bool DisableDelayedParsing)
+ bool DelayBodyParsing)
: Parser(
std::unique_ptr<Lexer>(new Lexer(
SF.getASTContext().LangOpts, SF.getASTContext().SourceMgr,
@@ -359,7 +371,7 @@
SF.shouldBuildSyntaxTree()
? TriviaRetentionMode::WithTrivia
: TriviaRetentionMode::WithoutTrivia)),
- SF, SIL, PersistentState, std::move(SPActions), DisableDelayedParsing) {}
+ SF, SIL, PersistentState, std::move(SPActions), DelayBodyParsing) {}
namespace {
@@ -480,7 +492,7 @@
SILParserTUStateBase *SIL,
PersistentParserState *PersistentState,
std::shared_ptr<SyntaxParseActions> SPActions,
- bool DisableDelayedParsing)
+ bool DelayBodyParsing)
: SourceMgr(SF.getASTContext().SourceMgr),
Diags(SF.getASTContext().Diags),
SF(SF),
@@ -488,7 +500,7 @@
SIL(SIL),
CurDeclContext(&SF),
Context(SF.getASTContext()),
- DisableDelayedParsing(DisableDelayedParsing),
+ DelayBodyParsing(DelayBodyParsing),
TokReceiver(SF.shouldCollectToken() ?
new TokenRecorder(SF) :
new ConsumeTokenReceiver()),
@@ -580,7 +592,7 @@
void Parser::markSplitToken(tok Kind, StringRef Txt) {
SplitTokens.emplace_back();
SplitTokens.back().setToken(Kind, Txt);
- Trivia EmptyTrivia;
+ ParsedTrivia EmptyTrivia;
SyntaxContext->addToken(SplitTokens.back(), LeadingTrivia, EmptyTrivia);
TokReceiver->receive(SplitTokens.back());
}
@@ -746,7 +758,7 @@
}
unsigned LexerOffset =
SourceMgr.getLocOffsetInBuffer(Tok.getLoc(), L->getBufferID());
- unsigned LeadingTriviaLen = LeadingTrivia.getTextLength();
+ unsigned LeadingTriviaLen = LeadingTrivia.getLength();
unsigned LeadingTriviaOffset = LexerOffset - LeadingTriviaLen;
SourceLoc LeadingTriviaLoc = Tok.getLoc().getAdvancedLoc(-LeadingTriviaLen);
if (auto TextLength = SyntaxContext->lookupNode(LeadingTriviaOffset,
@@ -1095,7 +1107,8 @@
Impl.SF->SyntaxParsingCache = SyntaxCache;
Impl.TheParser.reset(new Parser(BufferID, *Impl.SF, /*SIL=*/nullptr,
- /*PersistentState=*/nullptr, Impl.SPActions));
+ /*PersistentState=*/nullptr, Impl.SPActions,
+ /*DelayBodyParsing=*/false));
}
ParserUnit::ParserUnit(SourceManager &SM, SourceFileKind SFKind, unsigned BufferID,
@@ -1112,7 +1125,7 @@
TriviaRetentionMode::WithoutTrivia,
Offset, EndOffset));
Impl.TheParser.reset(new Parser(std::move(Lex), *Impl.SF, /*SIL=*/nullptr,
- /*PersistentState=*/nullptr, Impl.SPActions));
+ /*PersistentState=*/nullptr, Impl.SPActions, /*DelayBodyParsing=*/false));
}
ParserUnit::~ParserUnit() {
diff --git a/lib/Parse/SyntaxParsingContext.cpp b/lib/Parse/SyntaxParsingContext.cpp
index 9a3a908..a70c362 100644
--- a/lib/Parse/SyntaxParsingContext.cpp
+++ b/lib/Parse/SyntaxParsingContext.cpp
@@ -23,7 +23,6 @@
#include "swift/Parse/SyntaxParsingCache.h"
#include "swift/Parse/Token.h"
#include "swift/Syntax/SyntaxFactory.h"
-#include "swift/Syntax/Trivia.h"
using namespace swift;
using namespace swift::syntax;
@@ -67,7 +66,7 @@
ArrayRef<ParsedRawSyntaxNode> Parts) {
assert(isUnknownKind(Kind));
if (IsBacktracking)
- return ParsedRawSyntaxNode::makeDeferred(Kind, Parts);
+ return ParsedRawSyntaxNode::makeDeferred(Kind, Parts, *this);
else
return getRecorder().recordRawSyntax(Kind, Parts);
}
@@ -81,7 +80,7 @@
auto &rec = getRecorder();
auto formNode = [&](SyntaxKind kind, ArrayRef<ParsedRawSyntaxNode> layout) {
if (nodeCreateK == SyntaxNodeCreationKind::Deferred || IsBacktracking) {
- rawNode = ParsedRawSyntaxNode::makeDeferred(kind, layout);
+ rawNode = ParsedRawSyntaxNode::makeDeferred(kind, layout, *this);
} else {
rawNode = rec.recordRawSyntax(kind, layout);
}
@@ -171,14 +170,16 @@
}
/// Add Token with Trivia to the parts.
-void SyntaxParsingContext::addToken(Token &Tok, Trivia &LeadingTrivia,
- Trivia &TrailingTrivia) {
+void SyntaxParsingContext::addToken(Token &Tok,
+ const ParsedTrivia &LeadingTrivia,
+ const ParsedTrivia &TrailingTrivia) {
if (!Enabled)
return;
ParsedRawSyntaxNode raw;
if (IsBacktracking)
- raw = ParsedRawSyntaxNode::makeDeferred(Tok, LeadingTrivia, TrailingTrivia);
+ raw = ParsedRawSyntaxNode::makeDeferred(Tok, LeadingTrivia, TrailingTrivia,
+ *this);
else
raw = getRecorder().recordToken(Tok, LeadingTrivia, TrailingTrivia);
addRawSyntax(std::move(raw));
@@ -229,8 +230,6 @@
case SyntaxKind::IdentifierExpr:
case SyntaxKind::SpecializeExpr:
case SyntaxKind::MemberAccessExpr:
- case SyntaxKind::DotSelfExpr:
- case SyntaxKind::ImplicitMemberExpr:
case SyntaxKind::SimpleTypeIdentifier:
case SyntaxKind::MemberTypeIdentifier:
case SyntaxKind::FunctionCallExpr:
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index e31afb4..a8ecb77 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -116,19 +116,32 @@
PersistentParserState *PersistentState,
DelayedParsingCallbacks *DelayedParseCB,
bool FullParse,
- bool DisableDelayedParsing) {
+ bool DelayBodyParsing) {
assert((!FullParse || (SF.canBeParsedInFull() && !SIL)) &&
"cannot parse in full with the given parameters!");
std::shared_ptr<SyntaxTreeCreator> STreeCreator;
if (SF.shouldBuildSyntaxTree()) {
STreeCreator = std::make_shared<SyntaxTreeCreator>(
- SF.SyntaxParsingCache, SF.getASTContext().getSyntaxArena());
+ SF.getASTContext().SourceMgr, BufferID,
+ SF.SyntaxParsingCache, SF.getASTContext().getSyntaxArena());
}
+ // Not supported right now.
+ if (SF.Kind == SourceFileKind::REPL)
+ DelayBodyParsing = false;
+ if (SF.hasInterfaceHash())
+ DelayBodyParsing = false;
+ if (SF.shouldCollectToken())
+ DelayBodyParsing = false;
+ if (SF.shouldBuildSyntaxTree())
+ DelayBodyParsing = false;
+ if (SIL)
+ DelayBodyParsing = false;
+
SharedTimer timer("Parsing");
Parser P(BufferID, SF, SIL ? SIL->Impl.get() : nullptr,
- PersistentState, STreeCreator, DisableDelayedParsing);
+ PersistentState, STreeCreator, DelayBodyParsing);
PrettyStackTraceParser StackTrace(P);
llvm::SaveAndRestore<bool> S(P.IsParsingInterfaceTokens,
@@ -157,21 +170,21 @@
SILParserState *SIL,
PersistentParserState *PersistentState,
DelayedParsingCallbacks *DelayedParseCB,
- bool DisableDelayedParsing) {
+ bool DelayBodyParsing) {
return parseIntoSourceFileImpl(SF, BufferID, Done, SIL,
PersistentState, DelayedParseCB,
/*FullParse=*/SF.shouldBuildSyntaxTree(),
- DisableDelayedParsing);
+ DelayBodyParsing);
}
bool swift::parseIntoSourceFileFull(SourceFile &SF, unsigned BufferID,
PersistentParserState *PersistentState,
DelayedParsingCallbacks *DelayedParseCB,
- bool DisableDelayedParsing) {
+ bool DelayBodyParsing) {
bool Done = false;
return parseIntoSourceFileImpl(SF, BufferID, &Done, /*SIL=*/nullptr,
PersistentState, DelayedParseCB,
- /*FullParse=*/true, DisableDelayedParsing);
+ /*FullParse=*/true, DelayBodyParsing);
}
@@ -4921,13 +4934,16 @@
auto PartialApplyConvention = ParameterConvention::Direct_Owned;
bool IsNonThrowingApply = false;
+ bool IsNoEscape = false;
StringRef AttrName;
-
- if (parseSILOptional(AttrName, *this)) {
+
+ while (parseSILOptional(AttrName, *this)) {
if (AttrName.equals("nothrow"))
IsNonThrowingApply = true;
else if (AttrName.equals("callee_guaranteed"))
PartialApplyConvention = ParameterConvention::Direct_Guaranteed;
+ else if (AttrName.equals("on_stack"))
+ IsNoEscape = true;
else
return true;
}
@@ -5058,8 +5074,10 @@
}
// FIXME: Why the arbitrary order difference in IRBuilder type argument?
- ResultVal = B.createPartialApply(InstLoc, FnVal, subs, Args,
- PartialApplyConvention);
+ ResultVal = B.createPartialApply(
+ InstLoc, FnVal, subs, Args, PartialApplyConvention,
+ IsNoEscape ? PartialApplyInst::OnStackKind::OnStack
+ : PartialApplyInst::OnStackKind::NotOnStack);
break;
}
case SILInstructionKind::TryApplyInst: {
diff --git a/lib/SIL/LoopInfo.cpp b/lib/SIL/LoopInfo.cpp
index 3cb8bc1..84f55ef 100644
--- a/lib/SIL/LoopInfo.cpp
+++ b/lib/SIL/LoopInfo.cpp
@@ -101,6 +101,9 @@
if (isa<DynamicMethodBranchInst>(I))
return false;
+ if (auto *PA = dyn_cast<PartialApplyInst>(I))
+ return !PA->isOnStack();
+
assert(I->isTriviallyDuplicatable() &&
"Code here must match isTriviallyDuplicatable in SILInstruction");
return true;
diff --git a/lib/SIL/OperandOwnership.cpp b/lib/SIL/OperandOwnership.cpp
index f4cabbc..b967873 100644
--- a/lib/SIL/OperandOwnership.cpp
+++ b/lib/SIL/OperandOwnership.cpp
@@ -784,6 +784,10 @@
OperandOwnershipKindMap
OperandOwnershipKindClassifier::visitPartialApplyInst(PartialApplyInst *i) {
+ // partial_apply [stack] does not take ownership of its operands.
+ if (i->isOnStack())
+ return Map::allLive();
+
return Map::compatibilityMap(
// All non-trivial types should be captured.
ValueOwnershipKind::Owned, UseLifetimeConstraint::MustBeInvalidated);
diff --git a/lib/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index a84f732..e4a43b0 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -52,7 +52,8 @@
SILType SILBuilder::getPartialApplyResultType(SILType origTy, unsigned argCount,
SILModule &M,
SubstitutionMap subs,
- ParameterConvention calleeConvention) {
+ ParameterConvention calleeConvention,
+ PartialApplyInst::OnStackKind onStack) {
CanSILFunctionType FTI = origTy.castTo<SILFunctionType>();
if (!subs.empty())
FTI = FTI->substGenericArgs(M, subs);
@@ -65,6 +66,8 @@
auto extInfo = FTI->getExtInfo()
.withRepresentation(SILFunctionType::Representation::Thick)
.withIsPseudogeneric(false);
+ if (onStack)
+ extInfo = extInfo.withNoEscape();
// If the original method has an @unowned_inner_pointer return, the partial
// application thunk will lifetime-extend 'self' for us, converting the
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index c652c9e..60c41bf 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -2663,8 +2663,10 @@
AnyFunctionType::Param selfParam = fnType.getParams()[0];
// The formal method parameters.
+ // If we actually partially-apply this, assume we'll need a thick function.
fnType = cast<FunctionType>(fnType.getResult());
- auto innerExtInfo = fnType->getExtInfo();
+ auto innerExtInfo =
+ fnType->getExtInfo().withRepresentation(FunctionTypeRepresentation::Swift);
auto methodParams = fnType->getParams();
auto resultType = fnType.getResult();
diff --git a/lib/SIL/SILInstruction.cpp b/lib/SIL/SILInstruction.cpp
index bfac323..fc30594 100644
--- a/lib/SIL/SILInstruction.cpp
+++ b/lib/SIL/SILInstruction.cpp
@@ -1117,6 +1117,10 @@
if (ARI->canAllocOnStack())
return true;
}
+
+ if (auto *PA = dyn_cast<PartialApplyInst>(this))
+ return PA->isOnStack();
+
return false;
}
@@ -1189,6 +1193,9 @@
if (isa<DynamicMethodBranchInst>(this))
return false;
+ if (auto *PA = dyn_cast<PartialApplyInst>(this))
+ return !PA->isOnStack();
+
// If you add more cases here, you should also update SILLoop:canDuplicate.
return true;
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 28ab291..0afdb94 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -503,19 +503,19 @@
// PartialApplyInst
// should derive the type of its result by partially applying the callee's
// type.
- : InstructionBase(Loc, Callee, SubstCalleeTy, Subs,
- Args, TypeDependentOperands, SpecializationInfo,
- ClosureType) {}
+ : InstructionBase(Loc, Callee, SubstCalleeTy, Subs, Args,
+ TypeDependentOperands, SpecializationInfo, ClosureType) {}
PartialApplyInst *PartialApplyInst::create(
SILDebugLocation Loc, SILValue Callee, ArrayRef<SILValue> Args,
SubstitutionMap Subs, ParameterConvention CalleeConvention, SILFunction &F,
SILOpenedArchetypesState &OpenedArchetypes,
- const GenericSpecializationInformation *SpecializationInfo) {
+ const GenericSpecializationInformation *SpecializationInfo,
+ OnStackKind onStack) {
SILType SubstCalleeTy =
Callee->getType().substGenericArgs(F.getModule(), Subs);
SILType ClosureType = SILBuilder::getPartialApplyResultType(
- SubstCalleeTy, Args.size(), F.getModule(), {}, CalleeConvention);
+ SubstCalleeTy, Args.size(), F.getModule(), {}, CalleeConvention, onStack);
SmallVector<SILValue, 32> TypeDependentOperands;
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 5537923..9ac4a41 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -212,6 +212,10 @@
// FIXME
Buffer << "<subscript>";
return;
+ case DeclContextKind::EnumElementDecl:
+ // FIXME
+ Buffer << "<enum element>";
+ return;
}
llvm_unreachable("bad decl context");
}
@@ -1123,6 +1127,8 @@
case ParameterConvention::Indirect_InoutAliasable:
llvm_unreachable("unexpected callee convention!");
}
+ if (CI->isOnStack())
+ *this << "[on_stack] ";
visitApplyInstBase(CI);
}
diff --git a/lib/SIL/SILProfiler.cpp b/lib/SIL/SILProfiler.cpp
index 64a2d41..050682d 100644
--- a/lib/SIL/SILProfiler.cpp
+++ b/lib/SIL/SILProfiler.cpp
@@ -404,7 +404,7 @@
assert((!StartLoc || StartLoc->isValid()) &&
"Expected start location to be valid");
assert((!EndLoc || EndLoc->isValid()) &&
- "Expected start location to be valid");
+ "Expected end location to be valid");
}
SourceMappingRegion(SourceMappingRegion &&Region) = default;
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index f0c36c2..f1ed279 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -2260,8 +2260,11 @@
void checkDeallocStackInst(DeallocStackInst *DI) {
require(isa<SILUndef>(DI->getOperand()) ||
- isa<AllocStackInst>(DI->getOperand()),
- "Operand of dealloc_stack must be an alloc_stack");
+ isa<AllocStackInst>(DI->getOperand()) ||
+ (isa<PartialApplyInst>(DI->getOperand()) &&
+ cast<PartialApplyInst>(DI->getOperand())->isOnStack()),
+ "Operand of dealloc_stack must be an alloc_stack or partial_apply "
+ "[stack]");
}
void checkDeallocRefInst(DeallocRefInst *DI) {
require(DI->getOperand()->getType().isObject(),
diff --git a/lib/SIL/ValueOwnership.cpp b/lib/SIL/ValueOwnership.cpp
index d45a668..c9e3c10 100644
--- a/lib/SIL/ValueOwnership.cpp
+++ b/lib/SIL/ValueOwnership.cpp
@@ -74,7 +74,6 @@
CONSTANT_OWNERSHIP_INST(Owned, CopyBlockWithoutEscaping)
CONSTANT_OWNERSHIP_INST(Owned, CopyValue)
CONSTANT_OWNERSHIP_INST(Owned, KeyPath)
-CONSTANT_OWNERSHIP_INST(Owned, PartialApply)
CONSTANT_OWNERSHIP_INST(Owned, InitExistentialValue)
CONSTANT_OWNERSHIP_INST(Owned, GlobalValue) // TODO: is this correct?
@@ -330,6 +329,13 @@
llvm_unreachable("Unhandled LoadOwnershipQualifier in switch.");
}
+ValueOwnershipKind
+ValueOwnershipKindClassifier::visitPartialApplyInst(PartialApplyInst *PA) {
+ if (PA->isOnStack())
+ return ValueOwnershipKind::Any;
+ return ValueOwnershipKind::Owned;
+}
+
//===----------------------------------------------------------------------===//
// Builtin OwnershipValueKind Computation
//===----------------------------------------------------------------------===//
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 2cc12d0..feb4916 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -2292,9 +2292,13 @@
// Map outer initializations into a tuple of inner initializations:
// - fill out the initialization elements with null
TupleInitialization innerTupleInit;
- CanTupleType innerTuple =
- cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
- innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());
+ if (E->isSourceScalar()) {
+ innerTupleInit.SubInitializations.push_back(nullptr);
+ } else {
+ CanTupleType innerTuple =
+ cast<TupleType>(E->getSubExpr()->getType()->getCanonicalType());
+ innerTupleInit.SubInitializations.resize(innerTuple->getNumElements());
+ }
// Map all the outer initializations to their appropriate targets.
for (unsigned outerIndex = 0; outerIndex != outerInits.size(); outerIndex++) {
@@ -2312,14 +2316,20 @@
#endif
// Emit the sub-expression into the tuple initialization we just built.
- emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);
+ if (E->isSourceScalar()) {
+ emitter.SGF.emitExprInto(E->getSubExpr(),
+ innerTupleInit.SubInitializations[0].get());
+ } else {
+ emitter.SGF.emitExprInto(E->getSubExpr(), &innerTupleInit);
+ }
outerTupleInit->finishInitialization(emitter.SGF);
}
RValue RValueEmitter::visitTupleShuffleExpr(TupleShuffleExpr *E,
SGFContext C) {
- assert(!E->isSourceScalar());
+ // FIXME: Once we're no longer using this code path for enum element payloads,
+ // also assert that !E->isSourceScalar().
assert(!E->isResultScalar());
// If we're emitting into an initialization, we can try shuffling the
@@ -2333,7 +2343,11 @@
// Emit the sub-expression tuple and destructure it into elements.
SmallVector<RValue, 4> elements;
- visit(E->getSubExpr()).extractElements(elements);
+ if (E->isSourceScalar()) {
+ elements.push_back(visit(E->getSubExpr()));
+ } else {
+ visit(E->getSubExpr()).extractElements(elements);
+ }
// Prepare a new tuple to hold the shuffled result.
RValue result(E->getType()->getCanonicalType());
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index f524069..c4c32bd 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -668,12 +668,6 @@
CanAnyFunctionType blockTy,
CanSILFunctionType loweredBlockTy);
- /// Given a non-canonical function type, create a thunk for the function's
- /// canonical type.
- ManagedValue emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
- CanSILFunctionType nonCanonicalTy,
- CanSILFunctionType canonicalTy);
-
/// Thunk with the signature of a base class method calling a derived class
/// method.
///
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 9d13115..a8991af 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -1595,7 +1595,7 @@
auto &arg = managedArgs[index];
auto argTy = argTypes[index];
if (argTy.isConsumed()) {
- forwardedArgs.push_back(arg.forward(SGF));
+ forwardedArgs.push_back(arg.ensurePlusOne(SGF, loc).forward(SGF));
continue;
}
@@ -3906,150 +3906,3 @@
scope.pop();
B.createReturn(loc, reqtResultValue);
}
-
-//===----------------------------------------------------------------------===//
-// Conversion to Canonical SILFunctionType Thunks
-//===----------------------------------------------------------------------===//
-
-static void translateParametersForCanonicalFunctionThunk(
- SILGenFunction &SGF, SILLocation loc,
- ArrayRef<ManagedValue> origParamValues,
- ArrayRef<SILParameterInfo> newParamInfos,
- SmallVectorImpl<ManagedValue> &newParams) {
- assert(origParamValues.size() == newParamInfos.size());
-
- for (auto T : llvm::zip(origParamValues, newParamInfos)) {
- ManagedValue origParam;
- SILParameterInfo newParamInfo;
- std::tie(origParam, newParamInfo) = T;
-
- if (origParam.getType().isTrivial(SGF.getModule())) {
- newParams.emplace_back(origParam);
- continue;
- }
-
- if (origParam.hasCleanup()) {
- // If we have a +1 value and the non-canonical function expects a
- // guaranteed parameter, borrow the parameter. Otherwise just pass off the
- // +1 value.
- if (newParamInfo.isGuaranteed()) {
- origParam = origParam.borrow(SGF, loc);
- }
- newParams.emplace_back(origParam);
- continue;
- }
-
- // Otherwise, if we have a +0 value and we want to pass it off as a +1
- // value, perform the copy.
- if (newParamInfo.isConsumed()) {
- origParam = origParam.copy(SGF, loc);
- }
- newParams.emplace_back(origParam);
- }
-}
-
-static void buildCanonicalFunctionThunkBody(SILGenFunction &SGF,
- SILLocation loc,
- CanSILFunctionType nonCanonicalTy,
- CanSILFunctionType canonicalTy) {
- SGF.F.setBare(IsBare);
- SGF.F.setThunk(IsThunk);
-
- FullExpr scope(SGF.Cleanups, CleanupLocation::get(loc));
- FormalEvaluationScope formalEvalScope(SGF);
-
- // Collect the thunk params, creating arguments for each parameter.
- SmallVector<ManagedValue, 8> origParams;
- SGF.collectThunkParams(loc, origParams);
-
- // Then translate our parameters into new params.
- SmallVector<ManagedValue, 8> newParams;
- translateParametersForCanonicalFunctionThunk(
- SGF, loc,
- // We drop the front so we don't process the thunked function here. We
- // handle that later.
- llvm::makeArrayRef(origParams).drop_back(1),
- nonCanonicalTy->getParameters(), newParams);
-
- // Then grab the function we are going to call from the last parameter.
- ManagedValue fn = origParams.back();
-
- // Collect the arguments.
- SmallVector<SILValue, 8> args;
-
- // Add all of the indirect results. We can just add the SILValues directly to
- // the args array since we do not need to perform any transformations upon
- // them because:
- //
- // 1. Reabstraction can not occur as a result of a canonical/non-canonical
- // mismatch.
- // 2. SILGenFunction::collectThunkParams(...) does not create cleanups when it
- // creates arguments.
- SILFunctionConventions fnConv(canonicalTy, SGF.SGM.M);
- transform(range(fnConv.getNumIndirectSILResults()), std::back_inserter(args),
- [&](unsigned Index) -> SILValue {
- return SGF.F.begin()->getArgument(Index);
- });
-
- // and then the rest of the arguments besides the first argument. Here we have
- // to forward the arguments since collectThunkParams /does/ create cleanups
- // for the parameters.
- forwardFunctionArguments(SGF, loc, nonCanonicalTy, newParams, args);
-
- // Perform the call.
- SILValue result =
- SGF.emitApplyWithRethrow(loc, fn.forward(SGF), fn.getType(), {}, args);
-
- formalEvalScope.pop();
- scope.pop();
- SGF.B.createReturn(loc, result);
-}
-
-ManagedValue
-SILGenFunction::emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
- CanSILFunctionType nonCanonicalTy,
- CanSILFunctionType canonicalTy) {
- canonicalTy = canonicalTy->getWithRepresentation(
- SILFunctionType::Representation::Thick);
-
- SubstitutionMap contextSubs, interfaceSubs;
- GenericEnvironment *genericEnv = nullptr;
-
- // These two are not used here -- but really, bridging thunks
- // should be emitted using the formal AST type, not the lowered
- // type
- CanType inputSubstType;
- CanType outputSubstType;
- CanType dynamicSelfType;
- auto thunkTy = buildThunkType(nonCanonicalTy, canonicalTy, inputSubstType,
- outputSubstType, genericEnv, interfaceSubs,
- dynamicSelfType);
- assert(!dynamicSelfType && "not implemented");
- auto thunk = SGM.getOrCreateReabstractionThunk(thunkTy, nonCanonicalTy,
- canonicalTy, F.isSerialized());
- if (thunk->empty()) {
- thunk->setGenericEnvironment(genericEnv);
- SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
- auto loc = RegularLocation::getAutoGeneratedLocation();
- buildCanonicalFunctionThunkBody(thunkSGF, loc, nonCanonicalTy, canonicalTy);
- }
-
- CanSILFunctionType substFnTy = thunkTy;
-
- if (thunkTy->getGenericSignature()) {
- substFnTy = thunkTy->substGenericArgs(F.getModule(), interfaceSubs);
- }
-
- // Create it in the current function.
- auto thunkValue = B.createFunctionRefFor(loc, thunk);
- ManagedValue thunkedFn = B.createPartialApply(
- loc, thunkValue, SILType::getPrimitiveObjectType(substFnTy),
- interfaceSubs, {fn},
- SILType::getPrimitiveObjectType(canonicalTy));
- if (canonicalTy->isNoEscape()) {
- auto &funcTL = getTypeLowering(canonicalTy);
- thunkedFn =
- B.createConvertFunction(loc, thunkedFn, funcTL.getLoweredType());
- }
- return thunkedFn;
-}
diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp
index baaa856..a008b2d 100644
--- a/lib/SILGen/SILGenThunk.cpp
+++ b/lib/SILGen/SILGenThunk.cpp
@@ -86,38 +86,41 @@
return ManagedValue::forUnmanaged(B.createFunctionRefFor(loc, F));
}
-static ManagedValue getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc,
- SILDeclRef thunk,
- ManagedValue selfArg,
- SubstitutionMap curriedSubs) {
+static std::pair<ManagedValue, SILDeclRef>
+getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk,
+ ManagedValue selfArg, SubstitutionMap curriedSubs) {
auto *vd = thunk.getDecl();
// Reference the next uncurrying level of the function.
SILDeclRef next = SILDeclRef(vd, thunk.kind);
assert(!next.isCurried);
+ auto constantInfo = SGF.SGM.Types.getConstantInfo(next);
+
// If the function is natively foreign, reference its foreign entry point.
if (requiresForeignToNativeThunk(vd))
- return ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next));
+ return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
+ next};
// If the thunk is a curry thunk for a direct method reference, we are
// doing a direct dispatch (eg, a fragile 'super.foo()' call).
if (thunk.isDirectReference)
- return ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next));
-
- auto constantInfo = SGF.SGM.Types.getConstantInfo(next);
+ return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
+ next};
if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
if (getMethodDispatch(func) == MethodDispatch::Class) {
// Use the dynamic thunk if dynamic.
if (vd->isObjCDynamic()) {
- return SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType);
+ return {SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType),
+ next};
}
auto methodTy = SGF.SGM.Types.getConstantOverrideType(next);
SILValue result =
SGF.emitClassMethodRef(loc, selfArg.getValue(), next, methodTy);
- return ManagedValue::forUnmanaged(result);
+ return {ManagedValue::forUnmanaged(result),
+ next.getOverriddenVTableEntry()};
}
// If the fully-uncurried reference is to a generic method, look up the
@@ -130,12 +133,13 @@
auto conformance = curriedSubs.lookupConformance(origSelfType, protocol);
auto result = SGF.B.createWitnessMethod(loc, substSelfType, *conformance,
next, constantInfo.getSILType());
- return ManagedValue::forUnmanaged(result);
+ return {ManagedValue::forUnmanaged(result), next};
}
}
// Otherwise, emit a direct call.
- return ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next));
+ return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
+ next};
}
void SILGenFunction::emitCurryThunk(SILDeclRef thunk) {
@@ -152,7 +156,8 @@
SILLocation loc(vd);
Scope S(*this, vd);
- auto thunkFnTy = SGM.Types.getConstantInfo(thunk).SILFnType;
+ auto thunkInfo = SGM.Types.getConstantInfo(thunk);
+ auto thunkFnTy = thunkInfo.SILFnType;
SILFunctionConventions fromConv(thunkFnTy, SGM.M);
auto selfTy = fromConv.getSILType(thunkFnTy->getSelfParameter());
@@ -162,11 +167,10 @@
// Forward substitutions.
auto subs = F.getForwardingSubstitutionMap();
- ManagedValue toFn = getNextUncurryLevelRef(*this, loc, thunk, selfArg, subs);
+ auto toFnAndRef = getNextUncurryLevelRef(*this, loc, thunk, selfArg, subs);
+ ManagedValue toFn = toFnAndRef.first;
+ SILDeclRef calleeRef = toFnAndRef.second;
- // FIXME: Using the type from the ConstantInfo instead of looking at
- // getConstantOverrideInfo() for methods looks suspect in the presence
- // of covariant overrides and multiple vtable entries.
SILType resultTy = fromConv.getSingleSILResultType();
resultTy = F.mapTypeIntoContext(resultTy);
auto substTy = toFn.getType().substGenericArgs(SGM.M, subs);
@@ -184,8 +188,27 @@
if (resultFnTy->isABICompatibleWith(closureFnTy).isCompatible()) {
toClosure = B.createConvertFunction(loc, toClosure, resultTy);
} else {
+ // Compute the partially-applied abstraction pattern for the callee:
+ // just grab the pattern for the curried fn ref and "call" it.
+ assert(!calleeRef.isCurried);
+ calleeRef.isCurried = true;
+ auto appliedFnPattern = SGM.Types.getConstantInfo(calleeRef).FormalPattern
+ .getFunctionResultType();
+
+ auto appliedThunkPattern =
+ thunkInfo.FormalPattern.getFunctionResultType();
+
+ // The formal type should be the same for the callee and the thunk.
+ auto formalType = thunkInfo.FormalType;
+ if (auto genericSubstType = dyn_cast<GenericFunctionType>(formalType)) {
+ formalType = genericSubstType.substGenericArgs(subs);
+ }
+ formalType = cast<AnyFunctionType>(formalType.getResult());
+
toClosure =
- emitCanonicalFunctionThunk(loc, toClosure, closureFnTy, resultFnTy);
+ emitTransformedValue(loc, toClosure,
+ appliedFnPattern, formalType,
+ appliedThunkPattern, formalType);
}
}
toClosure = S.popPreservingValue(toClosure);
diff --git a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
index 66e43ec..2407511 100644
--- a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
@@ -32,7 +32,7 @@
FunctionSummary &functionSummary = info->getSummary();
ArgumentSummary &argSummary =
functionSummary.getAccessForArgument(index);
- index++;
+ ++index;
auto *functionArg = cast<SILFunctionArgument>(arg);
// Only summarize @inout_aliasable arguments.
@@ -137,6 +137,9 @@
case SILInstructionKind::ApplyInst:
case SILInstructionKind::TryApplyInst:
return true;
+ // partial_apply [stack] is terminated by a dealloc_stack.
+ case SILInstructionKind::DeallocStackInst:
+ return true;
case SILInstructionKind::ConvertFunctionInst:
return llvm::all_of(cast<ConvertFunctionInst>(user)->getUses(),
@@ -423,7 +426,7 @@
os << ", ";
}
os << subAccess.getDescription(BaseType, M);
- index++;
+ ++index;
}
os << "]";
@@ -594,7 +597,7 @@
const IndexTrieNode *iter = subPath;
while (iter) {
- length++;
+ ++length;
iter = iter->getParent();
}
@@ -628,7 +631,7 @@
unsigned argCount = getArgumentCount();
os << "(";
- for (unsigned i = 0; i < argCount; i++) {
+ for (unsigned i = 0; i < argCount; ++i) {
if (i > 0) {
os << ", ";
}
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index 2e62fe1..7e681f2 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -1034,6 +1034,17 @@
return isPartialApplyNonEscapingUser(Op, PAI, State);
}
+ // A mark_dependence user on a partial_apply is safe.
+ if (auto *MD = dyn_cast<MarkDependenceInst>(User)) {
+ if (MD->getBase() == Op->get()) {
+ auto parent = MD->getValue();
+ while ((MD = dyn_cast<MarkDependenceInst>(parent))) {
+ parent = MD->getValue();
+ }
+ return isa<PartialApplyInst>(parent);
+ }
+ }
+
if (auto *PBI = dyn_cast<ProjectBoxInst>(User)) {
// It is assumed in later code that we will only have 1 project_box. This
// can be seen since there is no code for reasoning about multiple
@@ -1198,6 +1209,26 @@
return B.createProjectBox(Box->getLoc(), Box, 0);
}
+/// Change the base in mark_dependence.
+static void
+mapMarkDependenceArguments(SingleValueInstruction *root,
+ llvm::DenseMap<SILValue, SILValue> &map) {
+ for (auto *Use : root->getUses()) {
+ if (auto *MD = dyn_cast<MarkDependenceInst>(Use->getUser())) {
+ mapMarkDependenceArguments(MD, map);
+ auto iter = map.find(MD->getBase());
+ if (iter != map.end()) {
+ MD->setBase(iter->second);
+ }
+ // Remove mark_dependence on trivial values.
+ if (MD->getBase()->getType().isTrivial(MD->getModule())) {
+ MD->replaceAllUsesWith(MD->getValue());
+ MD->eraseFromParent();
+ }
+ }
+ }
+}
+
/// Given a partial_apply instruction and a set of promotable indices,
/// clone the closure with the promoted captures and replace the partial_apply
/// with a partial_apply of the new closure, fixing up reference counting as
@@ -1236,6 +1267,8 @@
unsigned OpCount = PAI->getNumOperands() - PAI->getNumTypeDependentOperands();
SmallVector<SILValue, 16> Args;
auto NumIndirectResults = calleeConv.getNumIndirectSILResults();
+ llvm::DenseMap<SILValue, SILValue> capturedMap;
+ llvm::SmallSet<SILValue, 16> newCaptures;
for (; OpNo != OpCount; ++OpNo) {
unsigned Index = OpNo - 1 + FirstIndex;
if (!PromotableIndices.count(Index)) {
@@ -1250,8 +1283,18 @@
SILValue Addr = getOrCreateProjectBoxHelper(Box);
auto &typeLowering = M.getTypeLowering(Addr->getType());
- Args.push_back(
- typeLowering.emitLoadOfCopy(B, PAI->getLoc(), Addr, IsNotTake));
+ auto newCaptured =
+ typeLowering.emitLoadOfCopy(B, PAI->getLoc(), Addr, IsNotTake);
+ Args.push_back(newCaptured);
+
+ capturedMap[Box] = newCaptured;
+ newCaptures.insert(newCaptured);
+
+ // A partial_apply [stack] does not own the captured argument but we must
+ // destroy the projected object. We will do so after having created the new
+ // partial_apply below.
+ if (PAI->isOnStack())
+ continue;
// Cleanup the captured argument.
//
@@ -1268,7 +1311,8 @@
// Create a new partial apply with the new arguments.
auto *NewPAI = B.createPartialApply(
PAI->getLoc(), FnVal, PAI->getSubstitutionMap(), Args,
- PAI->getType().getAs<SILFunctionType>()->getCalleeConvention());
+ PAI->getType().getAs<SILFunctionType>()->getCalleeConvention(),
+ PAI->isOnStack());
PAI->replaceAllUsesWith(NewPAI);
PAI->eraseFromParent();
if (FRI->use_empty()) {
@@ -1276,6 +1320,21 @@
// TODO: If this is the last use of the closure, and if it has internal
// linkage, we should remove it from the SILModule now.
}
+
+ if (NewPAI->isOnStack()) {
+ // Insert destroy's of new captured arguments.
+ for (auto *Use : NewPAI->getUses()) {
+ if (auto *DS = dyn_cast<DeallocStackInst>(Use->getUser())) {
+ B.setInsertionPoint(std::next(SILBasicBlock::iterator(DS)));
+ insertDestroyOfCapturedArguments(NewPAI, B, [&](SILValue arg) -> bool {
+ return newCaptures.count(arg);
+ });
+ }
+ }
+ // Map the mark dependence arguments.
+ mapMarkDependenceArguments(NewPAI, capturedMap);
+ }
+
return ClonedFn;
}
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index 6c1cdd6..0dc09f8 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -296,6 +296,11 @@
auto *T2TF = Builder.createThinToThickFunction(OrigPAI->getLoc(), FuncRef,
OrigPAI->getType());
OrigPAI->replaceAllUsesWith(T2TF);
+ // Remove any dealloc_stack users.
+ SmallVector<Operand*, 16> Uses(T2TF->getUses());
+ for (auto *Use : Uses)
+ if (auto *DS = dyn_cast<DeallocStackInst>(Use->getUser()))
+ DS->eraseFromParent();
recursivelyDeleteTriviallyDeadInstructions(OrigPAI, true);
LLVM_DEBUG(llvm::dbgs() << " Rewrote caller:\n" << *T2TF);
}
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 678b263..e25a59c 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -72,7 +72,9 @@
#include "swift/SILOptimizer/Utils/SILInliner.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
+#include "swift/SILOptimizer/Utils/StackNesting.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -130,7 +132,8 @@
SILValue
cloneCalleeConversion(SILValue calleeValue, SILValue NewClosure,
SILBuilder &Builder,
- SmallVectorImpl<PartialApplyInst *> &NeedsRelease);
+ SmallVectorImpl<PartialApplyInst *> &NeedsRelease,
+ llvm::DenseMap<SILValue, SILValue> &CapturedMap);
SILFunction *getCloned() { return &getBuilder().getFunction(); }
static SILFunction *cloneFunction(SILOptFunctionBuilder &FunctionBuilder,
@@ -192,7 +195,18 @@
}
bool closureHasRefSemanticContext() const {
- return isa<PartialApplyInst>(getClosure());
+ return isa<PartialApplyInst>(getClosure()) &&
+ !cast<PartialApplyInst>(getClosure())->isOnStack();
+ }
+
+ bool destroyIfPartialApplyStack(SILBuilder &B,
+ SingleValueInstruction *newClosure) const {
+ auto *PA = dyn_cast<PartialApplyInst>(newClosure);
+ if (!PA || !PA->isOnStack())
+ return false;
+ insertDestroyOfCapturedArguments(PA, B);
+ B.createDeallocStack(getClosure()->getLoc(), PA);
+ return true;
}
unsigned getClosureIndex() const { return ClosureIndex; }
@@ -207,12 +221,13 @@
SingleValueInstruction *
createNewClosure(SILBuilder &B, SILValue V,
llvm::SmallVectorImpl<SILValue> &Args) const {
- if (isa<PartialApplyInst>(getClosure()))
+ if (auto *PA = dyn_cast<PartialApplyInst>(getClosure()))
return B.createPartialApply(getClosure()->getLoc(), V, {}, Args,
getClosure()
->getType()
.getAs<SILFunctionType>()
- ->getCalleeConvention());
+ ->getCalleeConvention(),
+ PA->isOnStack());
assert(isa<ThinToThickFunctionInst>(getClosure()) &&
"We only support partial_apply and thin_to_thick_function");
@@ -256,6 +271,13 @@
return getClosureParameterInfo().isConsumed();
}
+ bool isClosureOnStack() const {
+ auto *PA = dyn_cast<PartialApplyInst>(getClosure());
+ if (!PA)
+ return false;
+ return PA->isOnStack();
+ }
+
bool isTrivialNoEscapeParameter() const {
auto ClosureParmFnTy =
getClosureParameterInfo().getType()->getAs<SILFunctionType>();
@@ -675,16 +697,29 @@
// Clone a chain of ConvertFunctionInsts.
SILValue ClosureSpecCloner::cloneCalleeConversion(
SILValue calleeValue, SILValue NewClosure, SILBuilder &Builder,
- SmallVectorImpl<PartialApplyInst *> &NeedsRelease) {
+ SmallVectorImpl<PartialApplyInst *> &NeedsRelease,
+ llvm::DenseMap<SILValue, SILValue> &CapturedMap) {
+
+ // There might be a mark dependence on a previous closure value. Therefore, we
+ // add all closure values to the map.
+ auto addToOldToNewClosureMap = [&](SILValue origValue,
+ SILValue newValue) -> SILValue {
+ assert(!CapturedMap.count(origValue));
+ CapturedMap[origValue] = newValue;
+ return newValue;
+ };
+
if (calleeValue == CallSiteDesc.getClosure())
- return NewClosure;
+ return addToOldToNewClosureMap(calleeValue, NewClosure);
if (auto *CFI = dyn_cast<ConvertFunctionInst>(calleeValue)) {
+ SILValue origCalleeValue = calleeValue;
calleeValue = cloneCalleeConversion(CFI->getOperand(), NewClosure, Builder,
- NeedsRelease);
- return Builder.createConvertFunction(CallSiteDesc.getLoc(), calleeValue,
- CFI->getType(),
- CFI->withoutActuallyEscaping());
+ NeedsRelease, CapturedMap);
+ return addToOldToNewClosureMap(
+ origCalleeValue, Builder.createConvertFunction(
+ CallSiteDesc.getLoc(), calleeValue, CFI->getType(),
+ CFI->withoutActuallyEscaping()));
}
if (auto *PAI = dyn_cast<PartialApplyInst>(calleeValue)) {
@@ -693,27 +728,52 @@
->getType()
.getAs<SILFunctionType>()
->isTrivialNoEscape());
+ SILValue origCalleeValue = calleeValue;
calleeValue = cloneCalleeConversion(PAI->getArgument(0), NewClosure,
- Builder, NeedsRelease);
+ Builder, NeedsRelease, CapturedMap);
auto FunRef = Builder.createFunctionRef(CallSiteDesc.getLoc(),
PAI->getReferencedFunction());
auto NewPA = Builder.createPartialApply(
CallSiteDesc.getLoc(), FunRef, {}, {calleeValue},
- PAI->getType().getAs<SILFunctionType>()->getCalleeConvention());
+ PAI->getType().getAs<SILFunctionType>()->getCalleeConvention(),
+ PAI->isOnStack());
+ // If the partial_apply is on stack we will emit a dealloc_stack in the
+ // epilog.
NeedsRelease.push_back(NewPA);
- return NewPA;
+ return addToOldToNewClosureMap(origCalleeValue, NewPA);
}
+ if (auto *MD = dyn_cast<MarkDependenceInst>(calleeValue)) {
+ SILValue origCalleeValue = calleeValue;
+ calleeValue = cloneCalleeConversion(MD->getValue(), NewClosure, Builder,
+ NeedsRelease, CapturedMap);
+ if (!CapturedMap.count(MD->getBase())) {
+ CallSiteDesc.getClosure()->dump();
+ MD->dump();
+ MD->getFunction()->dump();
+ }
+ assert(CapturedMap.count(MD->getBase()));
+ return addToOldToNewClosureMap(
+ origCalleeValue,
+ Builder.createMarkDependence(CallSiteDesc.getLoc(), calleeValue,
+ CapturedMap[MD->getBase()]));
+ }
+
+
auto *Cvt = cast<ConvertEscapeToNoEscapeInst>(calleeValue);
+ SILValue origCalleeValue = calleeValue;
calleeValue = cloneCalleeConversion(Cvt->getOperand(), NewClosure, Builder,
- NeedsRelease);
- return Builder.createConvertEscapeToNoEscape(
- CallSiteDesc.getLoc(), calleeValue, Cvt->getType(), true);
+ NeedsRelease, CapturedMap);
+ return addToOldToNewClosureMap(
+ origCalleeValue,
+ Builder.createConvertEscapeToNoEscape(CallSiteDesc.getLoc(), calleeValue,
+ Cvt->getType(), true));
}
/// Populate the body of the cloned closure, modifying instructions as
-/// necessary. This is where we create the actual specialized BB Arguments.
+/// necessary. This is where we create the actual specialized BB Arguments
void ClosureSpecCloner::populateCloned() {
+ bool needToUpdateStackNesting = false;
SILFunction *Cloned = getCloned();
SILFunction *ClosureUser = CallSiteDesc.getApplyCallee();
@@ -752,10 +812,15 @@
unsigned NumTotalParams = ClosedOverFunConv.getNumParameters();
unsigned NumNotCaptured = NumTotalParams - CallSiteDesc.getNumArguments();
llvm::SmallVector<SILValue, 4> NewPAIArgs;
+ llvm::DenseMap<SILValue, SILValue> CapturedMap;
+ unsigned idx = 0;
for (auto &PInfo : ClosedOverFunConv.getParameters().slice(NumNotCaptured)) {
auto paramTy = ClosedOverFunConv.getSILType(PInfo);
SILValue MappedValue = ClonedEntryBB->createFunctionArgument(paramTy);
NewPAIArgs.push_back(MappedValue);
+ auto CapturedVal =
+ cast<PartialApplyInst>(CallSiteDesc.getClosure())->getArgument(idx++);
+ CapturedMap[CapturedVal] = MappedValue;
}
SILBuilder &Builder = getBuilder();
@@ -770,8 +835,9 @@
// Clone a chain of ConvertFunctionInsts. This can create further
// reabstraction partial_apply instructions.
SmallVector<PartialApplyInst*, 4> NeedsRelease;
- SILValue ConvertedCallee = cloneCalleeConversion(
- CallSiteDesc.getClosureCallerArg(), NewClosure, Builder, NeedsRelease);
+ SILValue ConvertedCallee =
+ cloneCalleeConversion(CallSiteDesc.getClosureCallerArg(), NewClosure,
+ Builder, NeedsRelease, CapturedMap);
// Make sure that we actually emit the releases for reabstraction thunks. We
// have guaranteed earlier that we only allow reabstraction thunks if the
@@ -790,7 +856,8 @@
bool ClosureHasRefSemantics = CallSiteDesc.closureHasRefSemanticContext();
if ((CallSiteDesc.isClosureGuaranteed() ||
CallSiteDesc.isTrivialNoEscapeParameter()) &&
- (ClosureHasRefSemantics || !NeedsRelease.empty())) {
+ (ClosureHasRefSemantics || !NeedsRelease.empty() ||
+ CallSiteDesc.isClosureOnStack())) {
for (SILBasicBlock *BB : CallSiteDesc.getNonFailureExitBBs()) {
SILBasicBlock *OpBB = getOpBasicBlock(BB);
@@ -804,9 +871,17 @@
if (ClosureHasRefSemantics)
Builder.createReleaseValue(Loc, SILValue(NewClosure),
Builder.getDefaultAtomicity());
- for (auto PAI : NeedsRelease)
- Builder.createReleaseValue(Loc, SILValue(PAI),
- Builder.getDefaultAtomicity());
+ else
+ needToUpdateStackNesting |=
+ CallSiteDesc.destroyIfPartialApplyStack(Builder, NewClosure);
+ for (auto PAI : NeedsRelease) {
+ if (PAI->isOnStack())
+ needToUpdateStackNesting |=
+ CallSiteDesc.destroyIfPartialApplyStack(Builder, PAI);
+ else
+ Builder.createReleaseValue(Loc, SILValue(PAI),
+ Builder.getDefaultAtomicity());
+ }
continue;
}
@@ -825,11 +900,22 @@
if (ClosureHasRefSemantics)
Builder.createReleaseValue(Loc, SILValue(NewClosure),
Builder.getDefaultAtomicity());
- for (auto PAI : NeedsRelease)
- Builder.createReleaseValue(Loc, SILValue(PAI),
- Builder.getDefaultAtomicity());
+ else
+ needToUpdateStackNesting |=
+ CallSiteDesc.destroyIfPartialApplyStack(Builder, NewClosure);
+ for (auto PAI : NeedsRelease) {
+ if (PAI->isOnStack())
+ needToUpdateStackNesting |=
+ CallSiteDesc.destroyIfPartialApplyStack(Builder, PAI);
+ else
+ Builder.createReleaseValue(Loc, SILValue(PAI),
+ Builder.getDefaultAtomicity());
+ }
}
}
+ if (needToUpdateStackNesting) {
+ StackNesting().correctStackNesting(Cloned);
+ }
}
//===----------------------------------------------------------------------===//
@@ -913,6 +999,10 @@
return markReabstractionPartialApplyAsUsed(FirstClosure, Cvt->getOperand(),
UsedReabstractionClosure);
}
+ if (auto MD = dyn_cast<MarkDependenceInst>(Current)) {
+ return markReabstractionPartialApplyAsUsed(FirstClosure, MD->getValue(),
+ UsedReabstractionClosure);
+ }
llvm_unreachable("Unexpect instruction");
}
@@ -994,6 +1084,14 @@
// Live range end points.
SmallVector<SILInstruction *, 8> UsePoints;
+ // Set of possible arguments for mark_dependence. The base of a
+ // mark_dependence we copy must be available in the specialized function.
+ llvm::SmallSet<SILValue, 16> PossibleMarkDependenceBases;
+ if (auto *PA = dyn_cast<PartialApplyInst>(ClosureInst)) {
+ for (auto Opd : PA->getArguments())
+ PossibleMarkDependenceBases.insert(Opd);
+ }
+
bool HaveUsedReabstraction = false;
// Uses may grow in this loop.
for (size_t UseIndex = 0; UseIndex < Uses.size(); ++UseIndex) {
@@ -1004,10 +1102,12 @@
if (auto *CFI = dyn_cast<ConvertFunctionInst>(Use->getUser())) {
// Push Uses in reverse order so they are visited in forward order.
Uses.append(CFI->getUses().begin(), CFI->getUses().end());
+ PossibleMarkDependenceBases.insert(CFI);
continue;
}
if (auto *Cvt = dyn_cast<ConvertEscapeToNoEscapeInst>(Use->getUser())) {
Uses.append(Cvt->getUses().begin(), Cvt->getUses().end());
+ PossibleMarkDependenceBases.insert(Cvt);
continue;
}
@@ -1025,11 +1125,29 @@
.getAs<SILFunctionType>()
->isTrivialNoEscape()) {
Uses.append(PA->getUses().begin(), PA->getUses().end());
+ PossibleMarkDependenceBases.insert(PA);
HaveUsedReabstraction = true;
}
continue;
}
+ // Look through mark_dependence on partial_apply [stack].
+ if (auto *MD = dyn_cast<MarkDependenceInst>(Use->getUser())) {
+ // We can't copy a closure if the mark_dependence base is not
+ // available in the specialized function.
+ if (!PossibleMarkDependenceBases.count(MD->getBase()))
+ continue;
+ if (MD->getValue() == Use->get() &&
+ MD->getValue()->getType().is<SILFunctionType>() &&
+ MD->getValue()
+ ->getType()
+ .castTo<SILFunctionType>()
+ ->isTrivialNoEscape()) {
+ Uses.append(MD->getUses().begin(), MD->getUses().end());
+ continue;
+ }
+ }
+
// If this use is not a full apply site that we can process or an apply
// inst with substitutions, there is nothing interesting for us to do,
// so continue...
diff --git a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
index efae3ba..9b356e1 100644
--- a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
@@ -508,6 +508,8 @@
case SILInstructionKind::RetainValueInst:
case SILInstructionKind::ReleaseValueInst:
case SILInstructionKind::EndBorrowInst:
+ // partial_apply [stack] is matched with dealloc_stack.
+ case SILInstructionKind::DeallocStackInst:
// Benign use.
return;
case SILInstructionKind::TupleExtractInst:
diff --git a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp
index f00f8ec..be49685 100644
--- a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp
+++ b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp
@@ -21,6 +21,7 @@
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/CFG.h"
#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/StackNesting.h"
#include "llvm/Support/CommandLine.h"
@@ -186,9 +187,148 @@
SingleNonDebugNonRefCountUser, Memoized));
}
+/// Insert a mark_dependence for any non-trivial argument of a partial_apply.
+static SILValue insertMarkDependenceForCapturedArguments(PartialApplyInst *PAI,
+ SILBuilder &B) {
+ SILValue curr(PAI);
+ // Mark dependence on all non-trivial arguments.
+ for (auto &arg : PAI->getArgumentOperands()) {
+ if (arg.get()->getType().isTrivial(PAI->getModule()))
+ continue;
+ curr = B.createMarkDependence(PAI->getLoc(), curr, arg.get());
+ }
+
+ return curr;
+}
+
+/// Rewrite a partial_apply convert_escape_to_noescape sequence with a single
+/// apply/try_apply user to a partial_apply [stack] terminated with a
+/// dealloc_stack placed after the apply.
+///
+/// %p = partial_apply %f(%a, %b)
+/// %ne = convert_escape_to_noescape %p
+/// apply %f2(%p)
+/// destroy_value %p
+///
+/// =>
+///
+/// %p = partial_apply [stack] %f(%a, %b)
+/// %md = mark_dependence %p on %a
+/// %md2 = mark_dependence %md on %b
+/// apply %f2(%md2)
+/// dealloc_stack %p
+/// destroy_value %a
+/// destroy_value %b
+///
+/// Note: If the rewrite succeeded we have inserted a dealloc_stack. This
+/// dealloc_stack still needs to be balanced with other dealloc_stacks i.e the
+/// caller needs to use the StackNesting utility to update the dealloc_stack
+/// nesting.
+static bool tryRewriteToPartialApplyStack(
+ SILLocation &loc, PartialApplyInst *origPA,
+ ConvertEscapeToNoEscapeInst *cvt, SILInstruction *singleApplyUser,
+ SILBasicBlock::iterator &advanceIfDelete,
+ llvm::DenseMap<SILInstruction *, SILInstruction *> &Memoized) {
+
+ auto *convertOrPartialApply = cast<SingleValueInstruction>(origPA);
+ if (cvt->getOperand() != origPA)
+ convertOrPartialApply = cast<ConvertFunctionInst>(cvt->getOperand());
+
+ // Whenever we delete an instruction advance the iterator and remove the
+ // instruction from the memoized map.
+ auto saveDeleteInst = [&](SILInstruction *I) {
+ if (&*advanceIfDelete == I)
+ advanceIfDelete++;
+ Memoized.erase(I);
+ I->eraseFromParent();
+ };
+
+ // Look for a single non ref count user of the partial_apply.
+ SmallVector<SILInstruction *, 8> refCountInsts;
+ SILInstruction *singleNonDebugNonRefCountUser = nullptr;
+ for (auto *Usr : getNonDebugUses(convertOrPartialApply)) {
+ auto *I = Usr->getUser();
+ if (onlyAffectsRefCount(I)) {
+ refCountInsts.push_back(I);
+ continue;
+ }
+ if (singleNonDebugNonRefCountUser)
+ return false;
+ singleNonDebugNonRefCountUser = I;
+ }
+
+ SILBuilderWithScope B(cvt);
+
+ // The convert_escape_to_noescape is the only user of the partial_apply.
+ // Convert to a partial_apply [stack].
+ SmallVector<SILValue, 8> args;
+ for (auto &arg : origPA->getArgumentOperands())
+ args.push_back(arg.get());
+ auto newPA = B.createPartialApply(
+ origPA->getLoc(), origPA->getCallee(), origPA->getSubstitutionMap(), args,
+ origPA->getType().getAs<SILFunctionType>()->getCalleeConvention(),
+ PartialApplyInst::OnStackKind::OnStack);
+
+ // Insert mark_dependence for any non-trivial operand to the partial_apply.
+ auto closure = insertMarkDependenceForCapturedArguments(newPA, B);
+
+ // Optionally, replace the convert_function instruction.
+ if (auto *convert = dyn_cast<ConvertFunctionInst>(convertOrPartialApply)) {
+ auto origTy = convert->getType().castTo<SILFunctionType>();
+ auto origWithNoEscape = SILType::getPrimitiveObjectType(
+ origTy->getWithExtInfo(origTy->getExtInfo().withNoEscape()));
+ closure = B.createConvertFunction(convert->getLoc(), closure, origWithNoEscape, false);
+ convert->replaceAllUsesWith(closure);
+ }
+
+ // Replace the convert_escape_to_noescape uses with the new
+ // partial_apply [stack].
+ cvt->replaceAllUsesWith(closure);
+ saveDeleteInst(cvt);
+
+ // Delete the ref count operations on the original partial_apply.
+ for (auto *refInst : refCountInsts)
+ saveDeleteInst(refInst);
+ convertOrPartialApply->replaceAllUsesWith(newPA);
+ if (convertOrPartialApply != origPA)
+ saveDeleteInst(convertOrPartialApply);
+ saveDeleteInst(origPA);
+
+ // Insert destroys of arguments after the apply and the dealloc_stack.
+ if (auto *Apply = dyn_cast<ApplyInst>(singleApplyUser)) {
+ auto InsertPt = std::next(SILBasicBlock::iterator(Apply));
+ // Don't insert dealloc_stacks at unreachable.
+ if (isa<UnreachableInst>(*InsertPt))
+ return true;
+ SILBuilderWithScope B3(InsertPt);
+ B3.createDeallocStack(loc, newPA);
+ insertDestroyOfCapturedArguments(newPA, B3);
+ } else if (auto *Try = dyn_cast<TryApplyInst>(singleApplyUser)) {
+ for (auto *SuccBB : Try->getSuccessorBlocks()) {
+ SILBuilderWithScope B3(SuccBB->begin());
+ B3.createDeallocStack(loc, newPA);
+ insertDestroyOfCapturedArguments(newPA, B3);
+ }
+ } else {
+ llvm_unreachable("Unknown FullApplySite instruction kind");
+ }
+ return true;
+}
+
+static SILValue skipConvert(SILValue v) {
+ auto cvt = dyn_cast<ConvertFunctionInst>(v);
+ if (!cvt)
+ return v;
+ auto *pa = dyn_cast<PartialApplyInst>(cvt->getOperand());
+ if (!pa || !pa->hasOneUse())
+ return v;
+ return pa;
+}
+
static bool tryExtendLifetimeToLastUse(
ConvertEscapeToNoEscapeInst *Cvt,
- llvm::DenseMap<SILInstruction *, SILInstruction *> &Memoized) {
+ llvm::DenseMap<SILInstruction *, SILInstruction *> &Memoized,
+ SILBasicBlock::iterator &AdvanceIfDelete) {
// If there is a single user that is an apply this is simple: extend the
// lifetime of the operand until after the apply.
auto SingleUser = lookThroughRebastractionUsers(Cvt, Memoized);
@@ -203,6 +343,12 @@
}
auto loc = RegularLocation::getAutoGeneratedLocation();
+ auto origPA = dyn_cast<PartialApplyInst>(skipConvert(Cvt->getOperand()));
+ if (origPA && tryRewriteToPartialApplyStack(
+ loc, origPA, Cvt, SingleApplyUser.getInstruction(),
+ AdvanceIfDelete,
+ Memoized))
+ return true;
// Insert a copy at the convert_escape_to_noescape [not_guaranteed] and
// change the instruction to the guaranteed form.
@@ -473,7 +619,7 @@
return true;
}
-static bool fixupClosureLifetimes(SILFunction &Fn) {
+static bool fixupClosureLifetimes(SILFunction &Fn, bool &checkStackNesting) {
bool Changed = false;
// tryExtendLifetimeToLastUse uses a cache of recursive instruction use
@@ -505,8 +651,9 @@
continue;
}
- if (tryExtendLifetimeToLastUse(Cvt, MemoizedQueries)) {
+ if (tryExtendLifetimeToLastUse(Cvt, MemoizedQueries, I)) {
Changed |= true;
+ checkStackNesting = true;
continue;
}
@@ -537,8 +684,21 @@
// Fixup convert_escape_to_noescape [not_guaranteed] and
// copy_block_without_escaping instructions.
- if (fixupClosureLifetimes(*getFunction()))
- invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
+
+ bool checkStackNesting = false;
+ bool modifiedCFG = false;
+
+ if (fixupClosureLifetimes(*getFunction(), checkStackNesting)) {
+ if (checkStackNesting){
+ StackNesting SN;
+ modifiedCFG =
+ SN.correctStackNesting(getFunction()) == StackNesting::Changes::CFG;
+ }
+ if (modifiedCFG)
+ invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
+ else
+ invalidateAnalysis(SILAnalysis::InvalidationKind::CallsAndInstructions);
+ }
LLVM_DEBUG(getFunction()->verify());
}
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
index 7ee60ec..e8afc71 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
@@ -956,8 +956,10 @@
static void checkNoEscapePartialApplyUse(Operand *oper, FollowUse followUses) {
SILInstruction *user = oper->getUser();
- // Ignore uses that are totally uninteresting.
- if (isIncidentalUse(user) || onlyAffectsRefCount(user))
+ // Ignore uses that are totally uninteresting. partial_apply [stack] is
+ // terminated by a dealloc_stack instruction.
+ if (isIncidentalUse(user) || onlyAffectsRefCount(user) ||
+ isa<DeallocStackInst>(user))
return;
// Before checking conversions in general below (getSingleValueCopyOrCast),
diff --git a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
index 391e493..a8890ab 100644
--- a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
+++ b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
@@ -373,6 +373,17 @@
return ThinToNoescapeCast->getOperand();
}
+ // Ignore mark_dependence users. A partial_apply [stack] uses them to mark
+ // the dependence of the trivial closure context value on the captured
+ // arguments.
+ if (auto *MD = dyn_cast<MarkDependenceInst>(CalleeValue)) {
+ while (MD) {
+ CalleeValue = MD->getValue();
+ MD = dyn_cast<MarkDependenceInst>(CalleeValue);
+ }
+ return CalleeValue;
+ }
+
auto *CFI = dyn_cast<ConvertEscapeToNoEscapeInst>(CalleeValue);
if (!CFI)
return CalleeValue;
diff --git a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
index bfed58f..ecf3801 100644
--- a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
+++ b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp
@@ -238,13 +238,6 @@
continue;
}
-#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
- if (isa<Load##Name##Inst>(User)) { \
- Uses.emplace_back(User, PMOUseKind::Load); \
- continue; \
- }
-#include "swift/AST/ReferenceStorage.def"
-
// Stores *to* the allocation are writes.
if (isa<StoreInst>(User) && UI->getOperandNumber() == 1) {
if (PointeeType.is<TupleType>()) {
@@ -254,34 +247,15 @@
// Coming out of SILGen, we assume that raw stores are initializations,
// unless they have trivial type (which we classify as InitOrAssign).
- PMOUseKind Kind;
- if (InStructSubElement)
- Kind = PMOUseKind::PartialStore;
- else if (PointeeType.isTrivial(User->getModule()))
- Kind = PMOUseKind::InitOrAssign;
- else
- Kind = PMOUseKind::Initialization;
-
+ auto Kind = ([&]() -> PMOUseKind {
+ if (PointeeType.isTrivial(User->getModule()))
+ return PMOUseKind::InitOrAssign;
+ return PMOUseKind::Initialization;
+ })();
Uses.emplace_back(User, Kind);
continue;
}
-#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
- if (auto *SI = dyn_cast<Store##Name##Inst>(User)) { \
- if (UI->getOperandNumber() == 1) { \
- PMOUseKind Kind; \
- if (InStructSubElement) \
- Kind = PMOUseKind::PartialStore; \
- else if (SI->isInitializationOfDest()) \
- Kind = PMOUseKind::Initialization; \
- else \
- Kind = PMOUseKind::Assign; \
- Uses.emplace_back(User, Kind); \
- continue; \
- } \
- }
-#include "swift/AST/ReferenceStorage.def"
-
if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
// If this is a copy of a tuple, we should scalarize it so that we don't
// have an access that crosses elements.
@@ -294,16 +268,17 @@
// the destination, then this is an unknown assignment. Note that we'll
// revisit this instruction and add it to Uses twice if it is both a load
// and store to the same aggregate.
- PMOUseKind Kind;
- if (UI->getOperandNumber() == 0)
- Kind = PMOUseKind::Load;
- else if (InStructSubElement)
- Kind = PMOUseKind::PartialStore;
- else if (CAI->isInitializationOfDest())
- Kind = PMOUseKind::Initialization;
- else
- Kind = PMOUseKind::Assign;
-
+ //
+ // Inline constructor.
+ auto Kind = ([&]() -> PMOUseKind {
+ if (UI->getOperandNumber() == CopyAddrInst::Src)
+ return PMOUseKind::Load;
+ if (PointeeType.isTrivial(CAI->getModule()))
+ return PMOUseKind::InitOrAssign;
+ if (CAI->isInitializationOfDest())
+ return PMOUseKind::Initialization;
+ return PMOUseKind::Assign;
+ })();
Uses.emplace_back(User, Kind);
continue;
}
diff --git a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.h b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.h
index 348590d..9ceb4e4 100644
--- a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.h
+++ b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.h
@@ -116,9 +116,6 @@
/// value.
Assign,
- /// The instruction is a store to a member of a larger struct value.
- PartialStore,
-
/// An indirect 'inout' parameter of an Apply instruction.
InOutUse,
diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
index a5f41f6..3a36c73 100644
--- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
+++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
@@ -911,7 +911,7 @@
assert((LoadUse.isValid() || StoreUse.isValid()) &&
"we should have a load or a store, possibly both");
assert(StoreUse.isInvalid() || StoreUse.Kind == Assign ||
- StoreUse.Kind == PartialStore || StoreUse.Kind == Initialization);
+ StoreUse.Kind == Initialization || StoreUse.Kind == InitOrAssign);
// Now that we've emitted a bunch of instructions, including a load and store
// but also including other stuff, update the internal state of
@@ -930,6 +930,12 @@
// something else), track it as an access.
if (StoreUse.isValid()) {
StoreUse.Inst = NewInst;
+ // If our store use by the copy_addr is an assign, then we know that
+ // before we store the new value, we loaded the old value implying that
+ // our store is technically initializing memory when it occurs. So
+ // change the kind to Initialization.
+ if (StoreUse.Kind == Assign)
+ StoreUse.Kind = Initialization;
NonLoadUses[NewInst] = Uses.size();
Uses.push_back(StoreUse);
}
@@ -948,11 +954,6 @@
}
continue;
-#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
- case SILInstructionKind::Name##RetainInst: \
- case SILInstructionKind::Name##ReleaseInst: \
- case SILInstructionKind::StrongRetain##Name##Inst:
-#include "swift/AST/ReferenceStorage.def"
case SILInstructionKind::RetainValueInst:
case SILInstructionKind::StrongRetainInst:
case SILInstructionKind::StrongReleaseInst:
@@ -983,6 +984,18 @@
// Allocation Optimization
//===----------------------------------------------------------------------===//
+static SILType getMemoryType(AllocationInst *memory) {
+ // Compute the type of the memory object.
+ if (auto *abi = dyn_cast<AllocBoxInst>(memory)) {
+ assert(abi->getBoxType()->getLayout()->getFields().size() == 1 &&
+ "optimizing multi-field boxes not implemented");
+ return abi->getBoxType()->getFieldType(abi->getModule(), 0);
+ }
+
+ assert(isa<AllocStackInst>(memory));
+ return cast<AllocStackInst>(memory)->getElementType();
+}
+
namespace {
/// This performs load promotion and deletes synthesized allocations if all
@@ -1008,44 +1021,27 @@
AvailableValueDataflowContext DataflowContext;
public:
- AllocOptimize(AllocationInst *TheMemory, SmallVectorImpl<PMOMemoryUse> &Uses,
- SmallVectorImpl<SILInstruction *> &Releases);
+ AllocOptimize(AllocationInst *memory, SmallVectorImpl<PMOMemoryUse> &uses,
+ SmallVectorImpl<SILInstruction *> &releases)
+ : Module(memory->getModule()), TheMemory(memory),
+ MemoryType(getMemoryType(memory)),
+ NumMemorySubElements(getNumSubElements(MemoryType, Module)), Uses(uses),
+ Releases(releases),
+ DataflowContext(TheMemory, NumMemorySubElements, uses) {}
- bool doIt();
+ bool optimizeMemoryAccesses();
+ bool tryToRemoveDeadAllocation();
private:
bool promoteLoad(SILInstruction *Inst);
void promoteDestroyAddr(DestroyAddrInst *DAI,
MutableArrayRef<AvailableValue> Values);
- bool
- canPromoteDestroyAddr(DestroyAddrInst *DAI,
- llvm::SmallVectorImpl<AvailableValue> &AvailableValues);
-
- bool tryToRemoveDeadAllocation();
+ bool canPromoteDestroyAddr(DestroyAddrInst *DAI,
+ SmallVectorImpl<AvailableValue> &AvailableValues);
};
} // end anonymous namespace
-static SILType getMemoryType(AllocationInst *TheMemory) {
- // Compute the type of the memory object.
- if (auto *ABI = dyn_cast<AllocBoxInst>(TheMemory)) {
- assert(ABI->getBoxType()->getLayout()->getFields().size() == 1 &&
- "optimizing multi-field boxes not implemented");
- return ABI->getBoxType()->getFieldType(ABI->getModule(), 0);
- } else {
- assert(isa<AllocStackInst>(TheMemory));
- return cast<AllocStackInst>(TheMemory)->getElementType();
- }
-}
-
-AllocOptimize::AllocOptimize(AllocationInst *InputMemory,
- SmallVectorImpl<PMOMemoryUse> &InputUses,
- SmallVectorImpl<SILInstruction *> &InputReleases)
- : Module(InputMemory->getModule()), TheMemory(InputMemory),
- MemoryType(getMemoryType(TheMemory)),
- NumMemorySubElements(getNumSubElements(MemoryType, Module)),
- Uses(InputUses), Releases(InputReleases),
- DataflowContext(TheMemory, NumMemorySubElements, Uses) {}
/// If we are able to optimize \p Inst, return the source address that
/// instruction is loading from. If we can not optimize \p Inst, then just
@@ -1149,8 +1145,7 @@
/// Return true if we can promote the given destroy.
bool AllocOptimize::canPromoteDestroyAddr(
- DestroyAddrInst *DAI,
- llvm::SmallVectorImpl<AvailableValue> &AvailableValues) {
+ DestroyAddrInst *DAI, SmallVectorImpl<AvailableValue> &AvailableValues) {
SILValue Address = DAI->getOperand();
// We cannot promote destroys of address-only types, because we can't expose
@@ -1224,8 +1219,49 @@
DAI->eraseFromParent();
}
-/// tryToRemoveDeadAllocation - If the allocation is an autogenerated allocation
-/// that is only stored to (after load promotion) then remove it completely.
+namespace {
+
+struct DestroyAddrPromotionState {
+ ArrayRef<SILInstruction *> destroys;
+ SmallVector<unsigned, 8> destroyAddrIndices;
+ SmallVector<AvailableValue, 32> availableValueList;
+ SmallVector<unsigned, 8> availableValueStartOffsets;
+
+ DestroyAddrPromotionState(ArrayRef<SILInstruction *> destroys)
+ : destroys(destroys) {}
+
+ unsigned size() const {
+ return destroyAddrIndices.size();
+ }
+
+ void initializeForDestroyAddr(unsigned destroyAddrIndex) {
+ availableValueStartOffsets.push_back(availableValueList.size());
+ destroyAddrIndices.push_back(destroyAddrIndex);
+ }
+
+ std::pair<DestroyAddrInst *, MutableArrayRef<AvailableValue>>
+ getData(unsigned index) {
+ unsigned destroyAddrIndex = destroyAddrIndices[index];
+ unsigned startOffset = availableValueStartOffsets[index];
+ unsigned count;
+
+ if ((availableValueStartOffsets.size() - 1) != index) {
+ count = availableValueStartOffsets[index + 1] - startOffset;
+ } else {
+ count = availableValueList.size() - startOffset;
+ }
+
+ MutableArrayRef<AvailableValue> values(&availableValueList[startOffset],
+ count);
+ auto *dai = cast<DestroyAddrInst>(destroys[destroyAddrIndex]);
+ return {dai, values};
+ }
+};
+
+} // end anonymous namespace
+
+/// If the allocation is an autogenerated allocation that is only stored to
+/// (after load promotion) then remove it completely.
bool AllocOptimize::tryToRemoveDeadAllocation() {
assert((isa<AllocBoxInst>(TheMemory) || isa<AllocStackInst>(TheMemory)) &&
"Unhandled allocation case");
@@ -1236,29 +1272,32 @@
// 1. They are in a transparent function.
// 2. They are in a normal function, but didn't come from a VarDecl, or came
// from one that was autogenerated or inlined from a transparent function.
- SILLocation Loc = TheMemory->getLoc();
+ SILLocation loc = TheMemory->getLoc();
if (!TheMemory->getFunction()->isTransparent() &&
- Loc.getAsASTNode<VarDecl>() && !Loc.isAutoGenerated() &&
- !Loc.is<MandatoryInlinedLocation>())
+ loc.getAsASTNode<VarDecl>() && !loc.isAutoGenerated() &&
+ !loc.is<MandatoryInlinedLocation>())
return false;
// Check the uses list to see if there are any non-store uses left over after
// load promotion and other things PMO does.
- for (auto &U : Uses) {
+ for (auto &u : Uses) {
// Ignore removed instructions.
- if (U.Inst == nullptr) continue;
+ if (u.Inst == nullptr)
+ continue;
- switch (U.Kind) {
+ switch (u.Kind) {
case PMOUseKind::Assign:
- case PMOUseKind::PartialStore:
+ // Until we can promote the value being destroyed by the assign, we can
+ // not remove deallocations with such assigns.
+ return false;
case PMOUseKind::InitOrAssign:
break; // These don't prevent removal.
case PMOUseKind::Initialization:
- if (!isa<ApplyInst>(U.Inst) &&
+ if (!isa<ApplyInst>(u.Inst) &&
// A copy_addr that is not a take affects the retain count
// of the source.
- (!isa<CopyAddrInst>(U.Inst) ||
- cast<CopyAddrInst>(U.Inst)->isTakeOfSrc()))
+ (!isa<CopyAddrInst>(u.Inst) ||
+ cast<CopyAddrInst>(u.Inst)->isTakeOfSrc()))
break;
// FALL THROUGH.
LLVM_FALLTHROUGH;
@@ -1267,7 +1306,8 @@
case PMOUseKind::InOutUse:
case PMOUseKind::Escape:
LLVM_DEBUG(llvm::dbgs() << "*** Failed to remove autogenerated alloc: "
- "kept alive by: " << *U.Inst);
+ "kept alive by: "
+ << *u.Inst);
return false; // These do prevent removal.
}
}
@@ -1289,53 +1329,39 @@
// Otherwise removing the deallocation will drop any releases. Check that
// there is nothing preventing removal.
- llvm::SmallVector<unsigned, 8> DestroyAddrIndices;
- llvm::SmallVector<AvailableValue, 32> AvailableValueList;
- llvm::SmallVector<unsigned, 8> AvailableValueStartOffsets;
+ DestroyAddrPromotionState state(Releases);
- for (auto P : llvm::enumerate(Releases)) {
- auto *R = P.value();
- if (R == nullptr)
+ for (auto p : llvm::enumerate(Releases)) {
+ auto *r = p.value();
+ if (r == nullptr)
continue;
// We stash all of the destroy_addr that we see.
- if (auto *DAI = dyn_cast<DestroyAddrInst>(R)) {
- AvailableValueStartOffsets.push_back(AvailableValueList.size());
+ if (auto *dai = dyn_cast<DestroyAddrInst>(r)) {
+ state.initializeForDestroyAddr(p.index() /*destroyAddrIndex*/);
// Make sure we can actually promote this destroy addr. If we can not,
// then we must bail. In order to not gather available values twice, we
// gather the available values here that we will use to promote the
// values.
- if (!canPromoteDestroyAddr(DAI, AvailableValueList))
+ if (!canPromoteDestroyAddr(dai, state.availableValueList))
return false;
- DestroyAddrIndices.push_back(P.index());
continue;
}
LLVM_DEBUG(llvm::dbgs()
<< "*** Failed to remove autogenerated non-trivial alloc: "
"kept alive by release: "
- << *R);
+ << *r);
return false;
}
// If we reached this point, we can promote all of our destroy_addr.
- for (auto P : llvm::enumerate(DestroyAddrIndices)) {
- unsigned DestroyAddrIndex = P.value();
- unsigned AvailableValueIndex = P.index();
- unsigned StartOffset = AvailableValueStartOffsets[AvailableValueIndex];
- unsigned Count;
-
- if ((AvailableValueStartOffsets.size() - 1) != AvailableValueIndex) {
- Count = AvailableValueStartOffsets[AvailableValueIndex + 1] - StartOffset;
- } else {
- Count = AvailableValueList.size() - StartOffset;
- }
-
- MutableArrayRef<AvailableValue> Values(&AvailableValueList[StartOffset],
- Count);
- auto *DAI = cast<DestroyAddrInst>(Releases[DestroyAddrIndex]);
- promoteDestroyAddr(DAI, Values);
- Releases[DestroyAddrIndex] = nullptr;
+ for (unsigned i : range(state.size())) {
+ DestroyAddrInst *dai;
+ MutableArrayRef<AvailableValue> values;
+ std::tie(dai, values) = state.getData(i);
+ promoteDestroyAddr(dai, values);
+ // We do not need to unset releases, since we are going to exit here.
}
LLVM_DEBUG(llvm::dbgs() << "*** Removing autogenerated non-trivial alloc: "
@@ -1349,79 +1375,135 @@
return true;
}
-/// doIt - returns true on error.
-bool AllocOptimize::doIt() {
- bool Changed = false;
-
- // Don't try to optimize incomplete aggregates.
- if (MemoryType.aggregateHasUnreferenceableStorage())
- return false;
+bool AllocOptimize::optimizeMemoryAccesses() {
+ bool changed = false;
// If we've successfully checked all of the definitive initialization
// requirements, try to promote loads. This can explode copy_addrs, so the
// use list may change size.
for (unsigned i = 0; i != Uses.size(); ++i) {
- auto &Use = Uses[i];
+ auto &use = Uses[i];
// Ignore entries for instructions that got expanded along the way.
- if (Use.Inst && Use.Kind == PMOUseKind::Load) {
- if (promoteLoad(Use.Inst)) {
+ if (use.Inst && use.Kind == PMOUseKind::Load) {
+ if (promoteLoad(use.Inst)) {
Uses[i].Inst = nullptr; // remove entry if load got deleted.
- Changed = true;
+ changed = true;
}
}
}
-
- // If this is an allocation, try to remove it completely.
- Changed |= tryToRemoveDeadAllocation();
- return Changed;
+ return changed;
}
-static bool optimizeMemoryAllocations(SILFunction &Fn) {
- bool Changed = false;
- for (auto &BB : Fn) {
- auto I = BB.begin(), E = BB.end();
- while (I != E) {
- SILInstruction *Inst = &*I;
- if (!isa<AllocBoxInst>(Inst) && !isa<AllocStackInst>(Inst)) {
- ++I;
+//===----------------------------------------------------------------------===//
+// Top Level Entrypoints
+//===----------------------------------------------------------------------===//
+
+static AllocationInst *getOptimizableAllocation(SILInstruction *i) {
+ if (!isa<AllocBoxInst>(i) && !isa<AllocStackInst>(i)) {
+ return nullptr;
+ }
+
+ auto *alloc = cast<AllocationInst>(i);
+
+ // If our aggregate has unreferencable storage, we can't optimize. Return
+ // nullptr.
+ if (getMemoryType(alloc).aggregateHasUnreferenceableStorage())
+ return nullptr;
+
+ // Otherwise we are good to go. Lets try to optimize this memory!
+ return alloc;
+}
+
+static bool optimizeMemoryAccesses(SILFunction &fn) {
+ bool changed = false;
+ for (auto &bb : fn) {
+ auto i = bb.begin(), e = bb.end();
+ while (i != e) {
+ // First see if i is an allocation that we can optimize. If not, skip it.
+ AllocationInst *alloc = getOptimizableAllocation(&*i);
+ if (!alloc) {
+ ++i;
continue;
}
- auto Alloc = cast<AllocationInst>(Inst);
- LLVM_DEBUG(llvm::dbgs() << "*** PMO Optimize looking at: " << *Alloc
- << "\n");
- PMOMemoryObjectInfo MemInfo(Alloc);
+ LLVM_DEBUG(llvm::dbgs() << "*** PMO Optimize Memory Accesses looking at: "
+ << *alloc << "\n");
+ PMOMemoryObjectInfo memInfo(alloc);
// Set up the datastructure used to collect the uses of the allocation.
- SmallVector<PMOMemoryUse, 16> Uses;
- SmallVector<SILInstruction*, 4> Releases;
+ SmallVector<PMOMemoryUse, 16> uses;
+ SmallVector<SILInstruction *, 4> destroys;
// Walk the use list of the pointer, collecting them. If we are not able
// to optimize, skip this value. *NOTE* We may still scalarize values
// inside the value.
- if (!collectPMOElementUsesFrom(MemInfo, Uses, Releases)) {
- ++I;
+ if (!collectPMOElementUsesFrom(memInfo, uses, destroys)) {
+ ++i;
continue;
}
- Changed |= AllocOptimize(Alloc, Uses, Releases).doIt();
-
- // Carefully move iterator to avoid invalidation problems.
- ++I;
- if (Alloc->use_empty()) {
- Alloc->eraseFromParent();
+ AllocOptimize allocOptimize(alloc, uses, destroys);
+ changed |= allocOptimize.optimizeMemoryAccesses();
+
+ // Move onto the next instruction. We know this is safe since we do not
+ // eliminate allocations here.
+ ++i;
+ }
+ }
+
+ return changed;
+}
+
+static bool eliminateDeadAllocations(SILFunction &fn) {
+ bool changed = false;
+ for (auto &bb : fn) {
+ auto i = bb.begin(), e = bb.end();
+ while (i != e) {
+ // First see if i is an allocation that we can optimize. If not, skip it.
+ AllocationInst *alloc = getOptimizableAllocation(&*i);
+ if (!alloc) {
+ ++i;
+ continue;
+ }
+
+ LLVM_DEBUG(llvm::dbgs()
+ << "*** PMO Dead Allocation Elimination looking at: " << *alloc
+ << "\n");
+ PMOMemoryObjectInfo memInfo(alloc);
+
+ // Set up the datastructure used to collect the uses of the allocation.
+ SmallVector<PMOMemoryUse, 16> uses;
+ SmallVector<SILInstruction *, 4> destroys;
+
+ // Walk the use list of the pointer, collecting them. If we are not able
+ // to optimize, skip this value. *NOTE* We may still scalarize values
+ // inside the value.
+ if (!collectPMOElementUsesFrom(memInfo, uses, destroys)) {
+ ++i;
+ continue;
+ }
+
+ AllocOptimize allocOptimize(alloc, uses, destroys);
+ changed |= allocOptimize.tryToRemoveDeadAllocation();
+
+ // Move onto the next instruction. We know this is safe since we do not
+ // eliminate allocations here.
+ ++i;
+ if (alloc->use_empty()) {
+ alloc->eraseFromParent();
++NumAllocRemoved;
- Changed = true;
+ changed = true;
}
}
}
- return Changed;
+
+ return changed;
}
namespace {
-class PredictableMemoryOptimizations : public SILFunctionTransform {
+class PredictableMemoryAccessOptimizations : public SILFunctionTransform {
/// The entry point to the transformation.
///
/// FIXME: This pass should not need to rerun on deserialized
@@ -1430,14 +1512,25 @@
/// either indicates that this pass missing some opportunities the first time,
/// or has a pass order dependency on other early passes.
void run() override {
- if (optimizeMemoryAllocations(*getFunction()))
+ // TODO: Can we invalidate here just instructions?
+ if (optimizeMemoryAccesses(*getFunction()))
+ invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
+ }
+};
+
+class PredictableDeadAllocationElimination : public SILFunctionTransform {
+ void run() override {
+ if (eliminateDeadAllocations(*getFunction()))
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
}
};
} // end anonymous namespace
+SILTransform *swift::createPredictableMemoryAccessOptimizations() {
+ return new PredictableMemoryAccessOptimizations();
+}
-SILTransform *swift::createPredictableMemoryOptimizations() {
- return new PredictableMemoryOptimizations();
+SILTransform *swift::createPredictableDeadAllocationElimination() {
+ return new PredictableDeadAllocationElimination();
}
diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp
index 294ce42..d351b7f 100644
--- a/lib/SILOptimizer/PassManager/PassPipeline.cpp
+++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp
@@ -106,12 +106,20 @@
P.addOwnershipModelEliminator();
P.addMandatoryInlining();
P.addMandatorySILLinker();
- P.addPredictableMemoryOptimizations();
+
+ // Promote loads as necessary to ensure we have enough SSA formation to emit
+ // SSA based diagnostics.
+ P.addPredictableMemoryAccessOptimizations();
// Diagnostic ConstantPropagation must be rerun on deserialized functions
// because it is sensitive to the assert configuration.
// Consequently, certain optimization passes beyond this point will also rerun.
P.addDiagnosticConstantPropagation();
+
+ // Now that we have emitted constant propagation diagnostics, try to eliminate
+ // dead allocations.
+ P.addPredictableDeadAllocationElimination();
+
P.addGuaranteedARCOpts();
P.addDiagnoseUnreachable();
P.addDiagnoseInfiniteRecursion();
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 0fdfd4b..03138cc 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -74,9 +74,24 @@
SILInstruction *SILCombiner::visitPartialApplyInst(PartialApplyInst *PAI) {
// partial_apply without any substitutions or arguments is just a
// thin_to_thick_function.
- if (!PAI->hasSubstitutions() && (PAI->getNumArguments() == 0))
- return Builder.createThinToThickFunction(PAI->getLoc(), PAI->getCallee(),
- PAI->getType());
+ if (!PAI->hasSubstitutions() && (PAI->getNumArguments() == 0)) {
+ if (!PAI->isOnStack())
+ return Builder.createThinToThickFunction(PAI->getLoc(), PAI->getCallee(),
+ PAI->getType());
+
+ // Remove dealloc_stack of partial_apply [stack].
+ // Iterating while delete use a copy.
+ SmallVector<Operand *, 8> Uses(PAI->getUses());
+ for (auto *Use : Uses)
+ if (auto *dealloc = dyn_cast<DeallocStackInst>(Use->getUser()))
+ eraseInstFromFunction(*dealloc);
+ auto *thinToThick = Builder.createThinToThickFunction(
+ PAI->getLoc(), PAI->getCallee(), PAI->getType());
+ replaceInstUsesWith(*PAI, thinToThick);
+ eraseInstFromFunction(*PAI);
+ return nullptr;
+ }
+
// partial_apply %reabstraction_thunk_typeAtoB(
// partial_apply %reabstraction_thunk_typeBtoA %closure_typeB))
@@ -138,6 +153,12 @@
/// Returns true on success.
bool PartialApplyCombiner::allocateTemporaries() {
+ // A partial_apply [stack]'s argument are not owned by the partial_apply and
+ // therefore their lifetime must outlive any uses.
+ if (PAI->isOnStack()) {
+ return true;
+ }
+
// Copy the original arguments of the partial_apply into newly created
// temporaries and use these temporaries instead of the original arguments
// afterwards.
@@ -397,6 +418,15 @@
Uses.append(CFI->getUses().begin(), CFI->getUses().end());
continue;
}
+ // Look through mark_dependence users of partial_apply [stack].
+ if (auto *MD = dyn_cast<MarkDependenceInst>(User)) {
+ if (MD->getValue() == Use->get() &&
+ MD->getValue()->getType().is<SILFunctionType>() &&
+ MD->getValue()->getType().castTo<SILFunctionType>()->isNoEscape()) {
+ Uses.append(MD->getUses().begin(), MD->getUses().end());
+ }
+ continue;
+ }
// If this use of a partial_apply is not
// an apply which uses it as a callee, bail.
auto AI = FullApplySite::isa(User);
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index 0b19979..c01a13d 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -1843,6 +1843,26 @@
return simplifyTermWithIdenticalDestBlocks(ThisBB);
}
+bool onlyContainsRefcountAndDeallocStackInst(
+ SILBasicBlock::reverse_iterator I, SILBasicBlock::reverse_iterator End) {
+ while (I != End) {
+ auto MaybeDead = I++;
+ switch (MaybeDead->getKind()) {
+ // These technically have side effects, but not ones that matter
+ // in a block that we shouldn't really reach...
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::DeallocStackInst:
+ break;
+
+ default:
+ return false;
+ }
+ }
+ return true;
+}
/// simplifyUnreachableBlock - Simplify blocks ending with unreachable by
/// removing instructions that are safe to delete backwards until we
/// hit an instruction we cannot delete.
@@ -1853,6 +1873,8 @@
auto End = BB->rend();
SmallVector<SILInstruction *, 8> DeadInstrs;
+ bool canIgnoreRestOfBlock = false;
+
// Walk backwards deleting instructions that should be safe to delete
// in a block that ends with unreachable.
while (I != End) {
@@ -1866,10 +1888,19 @@
case SILInstructionKind::RetainValueInst:
case SILInstructionKind::ReleaseValueInst:
break;
-
+ // We can only ignore a dealloc_stack instruction if we can ignore all
+ // instructions in the block.
+ case SILInstructionKind::DeallocStackInst: {
+ if (canIgnoreRestOfBlock ||
+ onlyContainsRefcountAndDeallocStackInst(MaybeDead, End)) {
+ canIgnoreRestOfBlock = true;
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ }
default:
if (MaybeDead->mayHaveSideEffects()) {
- if (Changed)
+ if (Changed)
for (auto Dead : DeadInstrs)
Dead->eraseFromParent();
return Changed;
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index a94fc8f..1c9b872 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -2033,7 +2033,8 @@
if (auto *PAI = dyn_cast<PartialApplyInst>(AI)) {
auto *NewPAI = Builder.createPartialApply(
Loc, Callee, Subs, Arguments,
- PAI->getType().getAs<SILFunctionType>()->getCalleeConvention());
+ PAI->getType().getAs<SILFunctionType>()->getCalleeConvention(),
+ PAI->isOnStack());
PAI->replaceAllUsesWith(NewPAI);
return NewPAI;
}
@@ -2404,7 +2405,8 @@
auto Subs = ReInfo.getCallerParamSubstitutionMap();
auto *NewPAI = Builder.createPartialApply(
PAI->getLoc(), FRI, Subs, Arguments,
- PAI->getType().getAs<SILFunctionType>()->getCalleeConvention());
+ PAI->getType().getAs<SILFunctionType>()->getCalleeConvention(),
+ PAI->isOnStack());
PAI->replaceAllUsesWith(NewPAI);
DeadApplies.insert(PAI);
return;
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 31e19f3..b18f745 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -1138,14 +1138,50 @@
return true;
}
+static bool
+deadMarkDependenceUser(SILInstruction *Inst,
+ SmallVectorImpl<SILInstruction *> &DeleteInsts) {
+ if (!isa<MarkDependenceInst>(Inst))
+ return false;
+ DeleteInsts.push_back(Inst);
+ for (auto *Use : cast<SingleValueInstruction>(Inst)->getUses()) {
+ if (!deadMarkDependenceUser(Use->getUser(), DeleteInsts))
+ return false;
+ }
+ return true;
+}
+
/// TODO: Generalize this to general objects.
bool swift::tryDeleteDeadClosure(SingleValueInstruction *Closure,
InstModCallbacks Callbacks) {
+ auto *PA = dyn_cast<PartialApplyInst>(Closure);
+
// We currently only handle locally identified values that do not escape. We
// also assume that the partial apply does not capture any addresses.
- if (!isa<PartialApplyInst>(Closure) && !isa<ThinToThickFunctionInst>(Closure))
+ if (!PA && !isa<ThinToThickFunctionInst>(Closure))
return false;
+ // A stack allocated partial apply does not have any release users. Delete it
+ // if the only users are the dealloc_stack and mark_dependence instructions.
+ if (PA && PA->isOnStack()) {
+ SmallVector<SILInstruction*, 8> DeleteInsts;
+ for (auto *Use : PA->getUses()) {
+ if (isa<DeallocStackInst>(Use->getUser()) ||
+ isa<DebugValueInst>(Use->getUser()))
+ DeleteInsts.push_back(Use->getUser());
+ else if (!deadMarkDependenceUser(Use->getUser(), DeleteInsts))
+ return false;
+ }
+ for (auto *Inst : reverse(DeleteInsts))
+ Callbacks.DeleteInst(Inst);
+ Callbacks.DeleteInst(PA);
+
+ // Note: the lifetime of the captured arguments is managed outside of the
+ // trivial closure value i.e: there will already be releases for the
+ // captured arguments. Releasing captured arguments is not necessary.
+ return true;
+ }
+
// We only accept a user if it is an ARC object that can be removed if the
// object is dead. This should be expanded in the future. This also ensures
// that we are locally identified and non-escaping since we only allow for
@@ -1768,6 +1804,13 @@
std::back_inserter(worklist));
continue;
+ // A partial_apply [stack] marks its captured arguments with
+ // mark_dependence.
+ case SILInstructionKind::MarkDependenceInst:
+ copy(cast<SingleValueInstruction>(user)->getUses(),
+ std::back_inserter(worklist));
+ continue;
+
// Look through any reference count instructions since these are not
// escapes:
case SILInstructionKind::CopyValueInst:
@@ -1778,6 +1821,8 @@
case SILInstructionKind::RetainValueInst:
case SILInstructionKind::ReleaseValueInst:
case SILInstructionKind::DestroyValueInst:
+ // A partial_apply [stack] is deallocated with a dealloc_stack.
+ case SILInstructionKind::DeallocStackInst:
continue;
default:
break;
@@ -1793,3 +1838,22 @@
return None;
return f;
}
+
+/// Insert destroys of captured arguments of partial_apply [stack].
+void swift::insertDestroyOfCapturedArguments(
+ PartialApplyInst *PAI, SILBuilder &B,
+ llvm::function_ref<bool(SILValue)> shouldInsertDestroy) {
+ assert(PAI->isOnStack());
+
+ ApplySite site(PAI);
+ SILFunctionConventions calleeConv(site.getSubstCalleeType(),
+ PAI->getModule());
+ auto loc = RegularLocation::getAutoGeneratedLocation();
+ for (auto &arg : PAI->getArgumentOperands()) {
+ if (!shouldInsertDestroy(arg.get())) continue;
+ unsigned calleeArgumentIndex = site.getCalleeArgIndex(arg);
+ assert(calleeArgumentIndex >= calleeConv.getSILArgIndexOfFirstParam());
+ auto paramInfo = calleeConv.getParamInfoForSILArg(calleeArgumentIndex);
+ releasePartialApplyCapturedArg(B, loc, arg.get(), paramInfo);
+ }
+}
diff --git a/lib/SILOptimizer/Utils/StackNesting.cpp b/lib/SILOptimizer/Utils/StackNesting.cpp
index ceb0ea1..74e518a 100644
--- a/lib/SILOptimizer/Utils/StackNesting.cpp
+++ b/lib/SILOptimizer/Utils/StackNesting.cpp
@@ -110,7 +110,7 @@
BlockInfo *BI = WorkList.pop_back_val();
for (SILInstruction &I : *BI->Block) {
if (I.isAllocatingStack()) {
- auto Alloc = cast<AllocationInst>(&I);
+ auto Alloc = cast<SingleValueInstruction>(&I);
// Register this stack location.
unsigned CurrentBitNumber = StackLocs.size();
StackLoc2BitNumbers[Alloc] = CurrentBitNumber;
@@ -219,12 +219,16 @@
return isNested;
}
-static SILInstruction *createDealloc(AllocationInst *Alloc,
+static SILInstruction *createDealloc(SingleValueInstruction *Alloc,
SILInstruction *InsertionPoint,
SILLocation Location) {
SILBuilderWithScope B(InsertionPoint);
switch (Alloc->getKind()) {
+ case SILInstructionKind::PartialApplyInst:
case SILInstructionKind::AllocStackInst:
+ assert((isa<AllocStackInst>(Alloc) ||
+ cast<PartialApplyInst>(Alloc)->isOnStack()) &&
+ "wrong instruction");
return B.createDeallocStack(Location, Alloc);
case SILInstructionKind::AllocRefInst:
assert(cast<AllocRefInst>(Alloc)->canAllocOnStack());
@@ -248,7 +252,7 @@
for (int LocNr = AliveBefore.find_first(); LocNr >= 0;
LocNr = AliveBefore.find_next(LocNr)) {
if (!AliveAfter.test(LocNr)) {
- AllocationInst *Alloc = StackLocs[LocNr].Alloc;
+ auto *Alloc = StackLocs[LocNr].Alloc;
InsertionPoint = createDealloc(Alloc, InsertionPoint,
Location.hasValue() ? Location.getValue() : Alloc->getLoc());
changesMade = true;
@@ -374,13 +378,13 @@
dumpBits(BI.AliveStackLocsAtEntry);
for (SILInstruction *StackInst : BI.StackInsts) {
if (StackInst->isAllocatingStack()) {
- auto AllocInst = cast<AllocationInst>(StackInst);
+ auto AllocInst = cast<SingleValueInstruction>(StackInst);
int BitNr = StackLoc2BitNumbers.lookup(AllocInst);
llvm::dbgs() << " alloc #" << BitNr << ": alive=";
dumpBits(StackLocs[BitNr].AliveLocs);
llvm::dbgs() << " " << *StackInst;
} else if (StackInst->isDeallocatingStack()) {
- auto *AllocInst = cast<AllocationInst>(StackInst->getOperand(0));
+ auto *AllocInst = cast<SingleValueInstruction>(StackInst->getOperand(0));
int BitNr = StackLoc2BitNumbers.lookup(AllocInst);
llvm::dbgs() << " dealloc for #" << BitNr << "\n"
" " << *StackInst;
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 5f1c3a1..f5b4594 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -7808,23 +7808,31 @@
if (fixes == fixesPerExpr.end())
return false;
- bool diagnosed = false;
- for (const auto *fix : fixes->second)
- diagnosed |= fix->diagnose(E);
- return diagnosed;
+ bool diagnosedError = false;
+ for (const auto *fix : fixes->second) {
+ auto diagnosed = fix->diagnose(E);
+
+ if (fix->isWarning()) {
+ assert(diagnosed && "warnings should always be diagnosed");
+ (void)diagnosed;
+ } else {
+ diagnosedError |= diagnosed;
+ }
+ }
+ return diagnosedError;
};
- bool diagnosed = false;
+ bool diagnosedError = false;
E->forEachChildExpr([&](Expr *subExpr) -> Expr * {
// Diagnose root expression at the end to
// preserve ordering.
if (subExpr != E)
- diagnosed |= diagnoseExprFailures(subExpr);
+ diagnosedError |= diagnoseExprFailures(subExpr);
return subExpr;
});
- diagnosed |= diagnoseExprFailures(E);
- return diagnosed;
+ diagnosedError |= diagnoseExprFailures(E);
+ return diagnosedError;
}
/// Apply a given solution to the expression, producing a fully
@@ -7839,15 +7847,21 @@
if (shouldSuppressDiagnostics())
return nullptr;
- // If we can diagnose the problem with the fixits that we've pre-assumed,
- // do so now.
- if (applySolutionFixes(expr, solution))
- return nullptr;
+ bool diagnosedErrorsViaFixes = applySolutionFixes(expr, solution);
+ // If all of the available fixes would result in a warning,
+ // we can go ahead and apply this solution to AST.
+ if (!llvm::all_of(solution.Fixes, [](const ConstraintFix *fix) {
+ return fix->isWarning();
+ })) {
+ // If we already diagnosed any errors via fixes, that's it.
+ if (diagnosedErrorsViaFixes)
+ return nullptr;
- // If we didn't manage to diagnose anything well, so fall back to
- // diagnosing mining the system to construct a reasonable error message.
- diagnoseFailureForExpr(expr);
- return nullptr;
+ // If we didn't manage to diagnose anything well, so fall back to
+ // diagnosing mining the system to construct a reasonable error message.
+ diagnoseFailureForExpr(expr);
+ return nullptr;
+ }
}
// Mark any normal conformances used in this solution as "used".
diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h
index ea58e09..da1e3a2 100644
--- a/lib/Sema/CSFix.h
+++ b/lib/Sema/CSFix.h
@@ -111,14 +111,21 @@
FixKind Kind;
ConstraintLocator *Locator;
+ /// Determines whether this fix is simplify a warning which doesn't
+ /// require immediate source changes.
+ bool IsWarning;
+
public:
- ConstraintFix(ConstraintSystem &cs, FixKind kind, ConstraintLocator *locator)
- : CS(cs), Kind(kind), Locator(locator) {}
+ ConstraintFix(ConstraintSystem &cs, FixKind kind, ConstraintLocator *locator,
+ bool warning = false)
+ : CS(cs), Kind(kind), Locator(locator), IsWarning(warning) {}
virtual ~ConstraintFix();
FixKind getKind() const { return Kind; }
+ bool isWarning() const { return IsWarning; }
+
virtual std::string getName() const = 0;
/// Diagnose a failure associated with this fix given
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index a26bd8b..927598c 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -1504,17 +1504,33 @@
if (LiteralProtocols.size() <= 1)
return;
- llvm::SmallVector<Type, 2> defaultTypes;
- for (auto *protocol : LiteralProtocols)
- defaultTypes.push_back(CS.TC.getDefaultType(protocol, CS.DC));
+ llvm::SmallVector<std::pair<ProtocolDecl *, Type>, 2> candidates;
+ llvm::SmallVector<ProtocolDecl *, 2> skippedProtocols;
- auto result = 0;
- for (unsigned long i = 1; i < LiteralProtocols.size(); ++i) {
+ for (auto *protocol : LiteralProtocols) {
+ if (auto defaultType = CS.TC.getDefaultType(protocol, CS.DC)) {
+ candidates.push_back({protocol, defaultType});
+ continue;
+ }
+
+ // Looks like argument expected to conform to something like
+ // `ExpressibleByNilLiteral` which doesn't have a default
+ // type and as a result can't participate in minimalization.
+ skippedProtocols.push_back(protocol);
+ }
+
+ if (candidates.size() <= 1)
+ return;
+
+ unsigned result = 0;
+ for (unsigned i = 1, n = candidates.size(); i != n; ++i) {
+ const auto &candidate = candidates[i];
+
auto first =
- CS.TC.conformsToProtocol(defaultTypes[i], LiteralProtocols[result],
+ CS.TC.conformsToProtocol(candidate.second, candidates[result].first,
CS.DC, ConformanceCheckFlags::InExpression);
auto second =
- CS.TC.conformsToProtocol(defaultTypes[result], LiteralProtocols[i],
+ CS.TC.conformsToProtocol(candidates[result].second, candidate.first,
CS.DC, ConformanceCheckFlags::InExpression);
if ((first && second) || (!first && !second))
return;
@@ -1523,9 +1539,9 @@
result = i;
}
- auto *protocol = LiteralProtocols[result];
LiteralProtocols.clear();
- LiteralProtocols.insert(protocol);
+ LiteralProtocols.insert(candidates[result].first);
+ LiteralProtocols.insert(skippedProtocols.begin(), skippedProtocols.end());
}
void ConstraintSystem::ArgumentInfoCollector::dump() const {
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 5d478c9..51484c2 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -2871,7 +2871,8 @@
/// A set of all constraints which contribute to pontential bindings.
llvm::SmallPtrSet<Constraint *, 8> Sources;
- PotentialBindings(TypeVariableType *typeVar) : TypeVar(typeVar) {}
+ PotentialBindings(TypeVariableType *typeVar)
+ : TypeVar(typeVar), PotentiallyIncomplete(isGenericParameter()) {}
/// Determine whether the set of bindings is non-empty.
explicit operator bool() const { return !Bindings.empty(); }
@@ -2937,6 +2938,16 @@
/// Check if this binding is viable for inclusion in the set.
bool isViable(PotentialBinding &binding) const;
+ bool isGenericParameter() const {
+ if (auto *locator = TypeVar->getImpl().getLocator()) {
+ auto path = locator->getPath();
+ return path.empty() ? false
+ : path.back().getKind() ==
+ ConstraintLocator::GenericParameter;
+ }
+ return false;
+ }
+
void dump(llvm::raw_ostream &out,
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
out.indent(indent);
diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp
index 74bd513..1ed2d18 100644
--- a/lib/Sema/LookupVisibleDecls.cpp
+++ b/lib/Sema/LookupVisibleDecls.cpp
@@ -294,9 +294,9 @@
// These cases are probably impossible here but can also just
// be safely ignored.
- case DeclKind::EnumElement:
case DeclKind::Param:
case DeclKind::Module:
+ case DeclKind::EnumElement:
return;
// For other kinds of values, check if we already reported a decl
diff --git a/lib/Sema/TypeCheckError.cpp b/lib/Sema/TypeCheckError.cpp
index a967828..20ead77 100644
--- a/lib/Sema/TypeCheckError.cpp
+++ b/lib/Sema/TypeCheckError.cpp
@@ -155,6 +155,11 @@
}
}
+ // Constructor delegation.
+ if (auto otherCtorDeclRef = dyn_cast<OtherConstructorDeclRefExpr>(fn)) {
+ return AbstractFunction(otherCtorDeclRef->getDecl());
+ }
+
// Normal function references.
if (auto declRef = dyn_cast<DeclRefExpr>(fn)) {
ValueDecl *decl = declRef->getDecl();
diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp
index ecb9a49..9b87eee 100644
--- a/lib/Sema/TypeCheckNameLookup.cpp
+++ b/lib/Sema/TypeCheckNameLookup.cpp
@@ -574,18 +574,9 @@
return lookupMember(dc, type, DeclBaseName::createConstructor(), options);
}
-enum : unsigned {
- /// Never consider a candidate that's this distance away or worse.
- UnreasonableCallEditDistance = 8,
-
- /// Don't consider candidates that score worse than the given distance
- /// from the best candidate.
- MaxCallEditDistanceFromBestCandidate = 1
-};
-
-static unsigned getCallEditDistance(DeclName writtenName,
- DeclName correctedName,
- unsigned maxEditDistance) {
+unsigned TypeChecker::getCallEditDistance(DeclName writtenName,
+ DeclName correctedName,
+ unsigned maxEditDistance) {
// TODO: consider arguments.
// TODO: maybe ignore certain kinds of missing / present labels for the
// first argument label?
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index c62ba33..6e54386 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -31,6 +31,7 @@
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/Statistic.h"
+#include "swift/Basic/TopCollection.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/LocalContext.h"
#include "swift/Syntax/TokenKinds.h"
@@ -787,6 +788,7 @@
Stmt *visitBreakStmt(BreakStmt *S) {
LabeledStmt *Target = nullptr;
+ TopCollection<unsigned, LabeledStmt *> labelCorrections(3);
// Pick the nearest break target that matches the specified name.
if (S->getTargetName().empty()) {
for (auto I = ActiveLabeledStmts.rbegin(), E = ActiveLabeledStmts.rend();
@@ -806,31 +808,39 @@
if (S->getTargetName() == (*I)->getLabelInfo().Name) {
Target = *I;
break;
+ } else {
+ unsigned distance =
+ TC.getCallEditDistance(S->getTargetName(), (*I)->getLabelInfo().Name,
+ TypeChecker::UnreasonableCallEditDistance);
+ if (distance < TypeChecker::UnreasonableCallEditDistance)
+ labelCorrections.insert(distance, std::move(*I));
}
}
+ labelCorrections.filterMaxScoreRange(
+ TypeChecker::MaxCallEditDistanceFromBestCandidate);
}
if (!Target) {
// If we're in a defer, produce a tailored diagnostic.
if (isInDefer()) {
TC.diagnose(S->getLoc(), diag::jump_out_of_defer, "break");
- return nullptr;
+ } else if (S->getTargetName().empty()) {
+ // If we're dealing with an unlabeled break inside of an 'if' or 'do'
+ // statement, produce a more specific error.
+ if (std::any_of(ActiveLabeledStmts.rbegin(),
+ ActiveLabeledStmts.rend(),
+ [&](Stmt *S) -> bool {
+ return isa<IfStmt>(S) || isa<DoStmt>(S);
+ })) {
+ TC.diagnose(S->getLoc(), diag::unlabeled_break_outside_loop);
+ } else {
+ // Otherwise produce a generic error.
+ TC.diagnose(S->getLoc(), diag::break_outside_loop);
+ }
+ } else {
+ emitUnresolvedLabelDiagnostics(TC, S->getTargetLoc(), S->getTargetName(),
+ labelCorrections);
}
-
- auto diagid = diag::break_outside_loop;
-
- // If someone is using an unlabeled break inside of an 'if' or 'do'
- // statement, produce a more specific error.
- if (S->getTargetName().empty() &&
- std::any_of(ActiveLabeledStmts.rbegin(),
- ActiveLabeledStmts.rend(),
- [&](Stmt *S) -> bool {
- return isa<IfStmt>(S) || isa<DoStmt>(S);
- })) {
- diagid = diag::unlabeled_break_outside_loop;
- }
-
- TC.diagnose(S->getLoc(), diagid);
return nullptr;
}
S->setTarget(Target);
@@ -839,6 +849,7 @@
Stmt *visitContinueStmt(ContinueStmt *S) {
LabeledStmt *Target = nullptr;
+ TopCollection<unsigned, LabeledStmt *> labelCorrections(3);
// Scan to see if we are in any non-switch labeled statements (loops). Scan
// inside out.
if (S->getTargetName().empty()) {
@@ -858,31 +869,68 @@
if (S->getTargetName() == (*I)->getLabelInfo().Name) {
Target = *I;
break;
+ } else {
+ unsigned distance =
+ TC.getCallEditDistance(S->getTargetName(), (*I)->getLabelInfo().Name,
+ TypeChecker::UnreasonableCallEditDistance);
+ if (distance < TypeChecker::UnreasonableCallEditDistance)
+ labelCorrections.insert(distance, std::move(*I));
}
}
+ labelCorrections.filterMaxScoreRange(
+ TypeChecker::MaxCallEditDistanceFromBestCandidate);
}
- if (!Target) {
+ if (Target) {
+ // Continue cannot be used to repeat switches, use fallthrough instead.
+ if (!Target->isPossibleContinueTarget()) {
+ TC.diagnose(S->getLoc(), diag::continue_not_in_this_stmt,
+ isa<SwitchStmt>(Target) ? "switch" : "if");
+ return nullptr;
+ }
+ } else {
// If we're in a defer, produce a tailored diagnostic.
if (isInDefer()) {
TC.diagnose(S->getLoc(), diag::jump_out_of_defer, "break");
- return nullptr;
+ } else if (S->getTargetName().empty()) {
+ // If we're dealing with an unlabeled continue, produce a generic error.
+ TC.diagnose(S->getLoc(), diag::continue_outside_loop);
+ } else {
+ emitUnresolvedLabelDiagnostics(TC, S->getTargetLoc(), S->getTargetName(),
+ labelCorrections);
}
-
- TC.diagnose(S->getLoc(), diag::continue_outside_loop);
return nullptr;
}
-
- // Continue cannot be used to repeat switches, use fallthrough instead.
- if (!Target->isPossibleContinueTarget()) {
- TC.diagnose(S->getLoc(), diag::continue_not_in_this_stmt,
- isa<SwitchStmt>(Target) ? "switch" : "if");
- return nullptr;
- }
-
S->setTarget(Target);
return S;
}
+
+ static void
+ emitUnresolvedLabelDiagnostics(TypeChecker &tc, SourceLoc targetLoc, Identifier targetName,
+ TopCollection<unsigned, LabeledStmt *> corrections) {
+ // If an unresolved label was used, but we have a single correction,
+ // produce the specific diagnostic and fixit.
+ if (corrections.size() == 1) {
+ tc.diagnose(targetLoc, diag::unresolved_label_corrected,
+ targetName, corrections.begin()->Value->getLabelInfo().Name)
+ .highlight(SourceRange(targetLoc))
+ .fixItReplace(SourceRange(targetLoc),
+ corrections.begin()->Value->getLabelInfo().Name.str());
+ tc.diagnose(corrections.begin()->Value->getLabelInfo().Loc,
+ diag::identifier_declared_here,
+ corrections.begin()->Value->getLabelInfo().Name);
+ } else {
+ // If we have multiple corrections or none, produce a generic diagnostic
+ // and all corrections available.
+ tc.diagnose(targetLoc, diag::unresolved_label, targetName)
+ .highlight(SourceRange(targetLoc));
+ for (auto &entry : corrections)
+ tc.diagnose(entry.Value->getLabelInfo().Loc, diag::note_typo_candidate,
+ entry.Value->getLabelInfo().Name.str())
+ .fixItReplace(SourceRange(targetLoc),
+ entry.Value->getLabelInfo().Name.str());
+ }
+ }
Stmt *visitFallthroughStmt(FallthroughStmt *S) {
if (!SwitchLevel) {
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index de77826..6938e35 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -2128,6 +2128,20 @@
/// Attempt to omit needless words from the name of the given declaration.
Optional<Identifier> omitNeedlessWords(VarDecl *var);
+ /// Calculate edit distance between declaration names.
+ static unsigned getCallEditDistance(DeclName writtenName,
+ DeclName correctedName,
+ unsigned maxEditDistance);
+
+ enum : unsigned {
+ /// Never consider a candidate that's this distance away or worse.
+ UnreasonableCallEditDistance = 8,
+
+ /// Don't consider candidates that score worse than the given distance
+ /// from the best candidate.
+ MaxCallEditDistanceFromBestCandidate = 1
+ };
+
/// Check for a typo correction.
void performTypoCorrection(DeclContext *DC,
DeclRefKind refKind,
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 5dfdd56..0adb592 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -1023,8 +1023,8 @@
break;
case SIL_INST_APPLY: {
unsigned IsPartial;
- SILInstApplyLayout::readRecord(scratch, IsPartial, NumSubs,
- TyID, TyID2, ValID, ListOfValues);
+ SILInstApplyLayout::readRecord(scratch, IsPartial, NumSubs, TyID, TyID2,
+ ValID, ListOfValues);
switch (IsPartial) {
case SIL_APPLY:
RawOpCode = (unsigned)SILInstructionKind::ApplyInst;
@@ -1416,11 +1416,13 @@
for (unsigned I = 0, E = ListOfValues.size(); I < E; I++)
Args.push_back(getLocalValue(
ListOfValues[I], fnConv.getSILArgumentType(I + unappliedArgs)));
-
+ auto onStack = closureTy.castTo<SILFunctionType>()->isNoEscape()
+ ? PartialApplyInst::OnStackKind::OnStack
+ : PartialApplyInst::OnStackKind::NotOnStack;
// FIXME: Why the arbitrary order difference in IRBuilder type argument?
ResultVal = Builder.createPartialApply(
Loc, FnVal, Substitutions, Args,
- closureTy.castTo<SILFunctionType>()->getCalleeConvention());
+ closureTy.castTo<SILFunctionType>()->getCalleeConvention(), onStack);
break;
}
case SILInstructionKind::BuiltinInst: {
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 2cf0f79..0f41563 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -379,7 +379,7 @@
SIL_BEGIN_APPLY,
SIL_NON_THROWING_BEGIN_APPLY
};
-
+
using SILInstApplyLayout = BCRecordLayout<
SIL_INST_APPLY,
BCFixed<3>, // ApplyKind
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 6e7d95e..f6d34b6 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -475,6 +475,8 @@
return cast<AbstractFunctionDecl>(DC);
case DeclContextKind::SubscriptDecl:
return cast<SubscriptDecl>(DC);
+ case DeclContextKind::EnumElementDecl:
+ return cast<EnumElementDecl>(DC);
}
llvm_unreachable("Unhandled DeclContextKind in switch.");
@@ -1870,6 +1872,7 @@
case DeclContextKind::Initializer:
case DeclContextKind::TopLevelCodeDecl:
case DeclContextKind::SerializedLocal:
+ case DeclContextKind::EnumElementDecl:
llvm_unreachable("cannot cross-reference this context");
case DeclContextKind::FileUnit:
@@ -2405,6 +2408,7 @@
case DeclContextKind::SubscriptDecl:
case DeclContextKind::GenericTypeDecl:
case DeclContextKind::ExtensionDecl:
+ case DeclContextKind::EnumElementDecl:
declOrDeclContextID = addDeclRef(getDeclForContext(DC));
isDecl = true;
break;
diff --git a/lib/Syntax/Trivia.cpp.gyb b/lib/Syntax/Trivia.cpp.gyb
index 0e66837..389bb0f6 100644
--- a/lib/Syntax/Trivia.cpp.gyb
+++ b/lib/Syntax/Trivia.cpp.gyb
@@ -24,6 +24,20 @@
using namespace swift;
using namespace swift::syntax;
+TriviaPiece TriviaPiece::fromText(TriviaKind kind, StringRef text) {
+ switch (kind) {
+% for trivia in TRIVIAS:
+ case TriviaKind::${trivia.name}:
+% if trivia.is_collection():
+ assert(text.size() % ${trivia.characters_len()} == 0);
+ return TriviaPiece(kind, text.size()/${trivia.characters_len()});
+% else:
+ return TriviaPiece(kind, OwnedString::makeRefCounted(text));
+% end
+% end
+ }
+}
+
void TriviaPiece::dump(llvm::raw_ostream &OS, unsigned Indent) const {
for (decltype(Count) i = 0; i < Indent; ++i)
OS << ' ';
@@ -44,7 +58,7 @@
OS << ')';
}
-bool TriviaPiece::isComment() const {
+bool syntax::isCommentTriviaKind(TriviaKind Kind) {
switch (Kind) {
% for trivia in TRIVIAS:
case TriviaKind::${trivia.name}:
diff --git a/lib/SyntaxParse/SyntaxTreeCreator.cpp b/lib/SyntaxParse/SyntaxTreeCreator.cpp
index 9571328..a20bf39 100644
--- a/lib/SyntaxParse/SyntaxTreeCreator.cpp
+++ b/lib/SyntaxParse/SyntaxTreeCreator.cpp
@@ -14,6 +14,7 @@
#include "swift/Syntax/RawSyntax.h"
#include "swift/Syntax/SyntaxVisitor.h"
#include "swift/Syntax/Trivia.h"
+#include "swift/Parse/ParsedTrivia.h"
#include "swift/Parse/SyntaxParsingCache.h"
#include "swift/Parse/Token.h"
#include "swift/AST/ASTContext.h"
@@ -33,9 +34,11 @@
return raw;
}
-SyntaxTreeCreator::SyntaxTreeCreator(SyntaxParsingCache *syntaxCache,
+SyntaxTreeCreator::SyntaxTreeCreator(SourceManager &SM, unsigned bufferID,
+ SyntaxParsingCache *syntaxCache,
RC<syntax::SyntaxArena> arena)
- : Arena(std::move(arena)),
+ : SM(SM), BufferID(bufferID),
+ Arena(std::move(arena)),
SyntaxCache(syntaxCache),
TokenCache(new RawSyntaxTokenCache()) {
}
@@ -104,13 +107,30 @@
}
OpaqueSyntaxNode
-SyntaxTreeCreator::recordToken(const Token &tok,
- const syntax::Trivia &leadingTrivia,
- const syntax::Trivia &trailingTrivia,
+SyntaxTreeCreator::recordToken(tok tokenKind,
+ ArrayRef<ParsedTriviaPiece> leadingTriviaPieces,
+ ArrayRef<ParsedTriviaPiece> trailingTriviaPieces,
CharSourceRange range) {
- auto ownedText = OwnedString::makeRefCounted(tok.getText());
- auto raw = TokenCache->getToken(Arena, tok.getKind(), ownedText,
- leadingTrivia.Pieces, trailingTrivia.Pieces);
+ size_t leadingTriviaLen =
+ ParsedTriviaPiece::getTotalLength(leadingTriviaPieces);
+ size_t trailingTriviaLen =
+ ParsedTriviaPiece::getTotalLength(trailingTriviaPieces);
+ SourceLoc tokLoc = range.getStart().getAdvancedLoc(leadingTriviaLen);
+ unsigned tokLength = range.getByteLength() -
+ leadingTriviaLen - trailingTriviaLen;
+ CharSourceRange tokRange = CharSourceRange{tokLoc, tokLength};
+ SourceLoc leadingTriviaLoc = range.getStart();
+ SourceLoc trailingTriviaLoc = tokLoc.getAdvancedLoc(tokLength);
+ Trivia syntaxLeadingTrivia =
+ ParsedTriviaPiece::convertToSyntaxTrivia(leadingTriviaPieces,
+ leadingTriviaLoc, SM, BufferID);
+ Trivia syntaxTrailingTrivia =
+ ParsedTriviaPiece::convertToSyntaxTrivia(trailingTriviaPieces,
+ trailingTriviaLoc, SM, BufferID);
+ StringRef tokenText = SM.extractText(tokRange, BufferID);
+ auto ownedText = OwnedString::makeRefCounted(tokenText);
+ auto raw = TokenCache->getToken(Arena, tokenKind, ownedText,
+ syntaxLeadingTrivia.Pieces, syntaxTrailingTrivia.Pieces);
OpaqueSyntaxNode opaqueN = raw.get();
raw.resetWithoutRelease();
return opaqueN;
diff --git a/stdlib/public/Darwin/CMakeLists.txt b/stdlib/public/Darwin/CMakeLists.txt
index 2471ef9..90e53d1 100644
--- a/stdlib/public/Darwin/CMakeLists.txt
+++ b/stdlib/public/Darwin/CMakeLists.txt
@@ -8,7 +8,7 @@
list(APPEND SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES STATIC)
endif()
-set(all_overlays "Accelerate;AppKit;ARKit;AssetsLibrary;AVFoundation;CallKit;CloudKit;Contacts;CoreAudio;CoreData;CoreFoundation;CoreGraphics;CoreImage;CoreLocation;CoreMedia;CryptoTokenKit;Dispatch;Foundation;GameplayKit;GLKit;HomeKit;IOKit;Intents;MapKit;MediaPlayer;Metal;MetalKit;ModelIO;NaturalLanguage;Network;ObjectiveC;OpenCL;os;Photos;QuartzCore;SafariServices;SceneKit;simd;SpriteKit;UIKit;Vision;WatchKit;XCTest;XPC")
+set(all_overlays "Accelerate;AppKit;ARKit;AssetsLibrary;AVFoundation;CallKit;CloudKit;Compression;Contacts;CoreAudio;CoreData;CoreFoundation;CoreGraphics;CoreImage;CoreLocation;CoreMedia;CryptoTokenKit;Dispatch;Foundation;GameplayKit;GLKit;HomeKit;IOKit;Intents;MapKit;MediaPlayer;Metal;MetalKit;ModelIO;NaturalLanguage;Network;ObjectiveC;OpenCL;os;Photos;QuartzCore;SafariServices;SceneKit;simd;SpriteKit;UIKit;Vision;WatchKit;XCTest;XPC")
if(DEFINED SWIFT_OVERLAY_TARGETS)
set(overlays_to_build ${SWIFT_OVERLAY_TARGETS})
diff --git a/stdlib/public/Darwin/Compression/CMakeLists.txt b/stdlib/public/Darwin/Compression/CMakeLists.txt
new file mode 100644
index 0000000..52167e5
--- /dev/null
+++ b/stdlib/public/Darwin/Compression/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.4.3)
+include("../../../../cmake/modules/StandaloneOverlay.cmake")
+
+add_swift_target_library(swiftCompression ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
+ Compression.swift
+
+ SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+ LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}" "-lcompression"
+ SWIFT_MODULE_DEPENDS_OSX Darwin Foundation
+ SWIFT_MODULE_DEPENDS_IOS Darwin Foundation
+ SWIFT_MODULE_DEPENDS_TVOS Darwin Foundation
+ SWIFT_MODULE_DEPENDS_WATCHOS Darwin Foundation
+
+ DEPLOYMENT_VERSION_OSX ${SWIFTLIB_DEPLOYMENT_VERSION_COMPRESSION_OSX}
+ DEPLOYMENT_VERSION_IOS ${SWIFTLIB_DEPLOYMENT_VERSION_COMPRESSION_IOS}
+ DEPLOYMENT_VERSION_TVOS ${SWIFTLIB_DEPLOYMENT_VERSION_COMPRESSION_TVOS}
+ DEPLOYMENT_VERSION_WATCHOS ${SWIFTLIB_DEPLOYMENT_VERSION_COMPRESSION_WATCHOS}
+)
diff --git a/stdlib/public/Darwin/Compression/Compression.swift b/stdlib/public/Darwin/Compression/Compression.swift
new file mode 100644
index 0000000..265b18d
--- /dev/null
+++ b/stdlib/public/Darwin/Compression/Compression.swift
@@ -0,0 +1,305 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+import Darwin
+import Foundation
+@_exported import Compression
+
+/// Compression algorithms, wraps the C API constants.
+public enum Algorithm: CaseIterable {
+
+ /// LZFSE
+ case lzfse
+
+ /// Deflate (conforming to RFC 1951)
+ case zlib
+
+ /// LZ4 with simple frame encapsulation
+ case lz4
+
+ /// LZMA in a XZ container
+ case lzma
+
+ public var rawValue: compression_algorithm {
+ switch self {
+ case .lzfse: return COMPRESSION_LZFSE
+ case .zlib: return COMPRESSION_ZLIB
+ case .lz4: return COMPRESSION_LZ4
+ case .lzma: return COMPRESSION_LZMA
+ }
+ }
+}
+
+/// Compression errors
+public enum FilterError: Error {
+ /// Filter failed to initialize
+ case filterInitError
+
+ /// Invalid data in a call to compression_stream_process
+ case filterProcessError
+
+ /// Non-empty write after an output filter has been finalized
+ case writeToFinalizedFilter
+}
+
+/// Compression filter direction of operation, compress/decompress
+public enum FilterOperation {
+ /// Compress raw data to a compressed payload
+ case compress
+
+ /// Decompress a compressed payload to raw data
+ case decompress
+
+ public var rawValue: compression_stream_operation {
+ switch self {
+ case .compress: return COMPRESSION_STREAM_ENCODE
+ case .decompress: return COMPRESSION_STREAM_DECODE
+ }
+ }
+}
+
+@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+extension compression_stream {
+
+ /// Initialize a compression_stream struct
+ ///
+ /// - Parameter operation: direction of operation
+ /// - Parameter algorithm: compression algorithm
+ ///
+ /// - Throws: `FilterError.filterInitError` if `algorithm` is not supported
+ /// by the Compression stream API
+ ///
+ internal init(operation: FilterOperation, algorithm: Algorithm) throws {
+ self.init(dst_ptr: UnsafeMutablePointer<UInt8>.allocate(capacity:0),
+ dst_size: 0,
+ src_ptr: UnsafeMutablePointer<UInt8>.allocate(capacity:0),
+ src_size: 0,
+ state: nil)
+ let status = compression_stream_init(&self, operation.rawValue, algorithm.rawValue)
+ guard status == COMPRESSION_STATUS_OK else { throw FilterError.filterInitError }
+ }
+}
+
+@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+public class OutputFilter {
+ private var _stream: compression_stream
+ private var _buf: UnsafeMutablePointer<UInt8>
+ private let _bufCapacity: Int
+ private let _writeFunc: (Data?) throws -> ()
+ private var _finalized: Bool = false
+
+ /// Initialize an output filter
+ ///
+ /// - Parameters:
+ /// - operation: direction of operation
+ /// - algorithm: compression algorithm
+ /// - bufferCapacity: capacity of the internal data buffer
+ /// - writeFunc: called to write the processed data
+ ///
+ /// - Throws: `FilterError.StreamInitError` if stream initialization failed
+ public init(
+ _ operation: FilterOperation,
+ using algorithm: Algorithm,
+ bufferCapacity: Int = 65536,
+ writingTo writeFunc: @escaping (Data?) throws -> ()
+ ) throws {
+ _stream = try compression_stream(operation: operation, algorithm: algorithm)
+ _buf = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferCapacity)
+ _bufCapacity = bufferCapacity
+ _writeFunc = writeFunc
+ }
+
+ /// Send data to output filter
+ ///
+ /// Processed output will be sent to the output closure.
+ /// A call with empty/nil data is interpreted as finalize().
+ /// Writing non empty/nil data to a finalized stream is an error.
+ ///
+ /// - Parameter data: data to process
+ ///
+ /// - Throws:
+ /// `FilterError.filterProcessError` if an error occurs during processing
+ /// `FilterError.writeToFinalizedFilter` if `data` is not empty/nil, and the
+ /// filter is the finalized state
+ public func write(_ data: Data?) throws {
+ // Finalize if data is empty/nil
+ if data == nil || data!.isEmpty { try finalize() ; return }
+
+ // Fail if already finalized
+ if _finalized { throw FilterError.writeToFinalizedFilter }
+
+ // Process all incoming data
+ try data!.withUnsafeBytes { (src_ptr: UnsafePointer<UInt8>) in
+ _stream.src_size = data!.count
+ _stream.src_ptr = src_ptr
+ while (_stream.src_size > 0) { _ = try process(finalizing: false) }
+ }
+ }
+
+ /// Finalize the stream, i.e. flush all data remaining in the stream
+ ///
+ /// Processed output will be sent to the output closure.
+ /// When all output has been sent, the writingTo closure is called one last time with nil data.
+ /// Once the stream is finalized, writing non empty/nil data to the stream will throw an exception.
+ ///
+ /// - Throws: `FilterError.StreamProcessError` if an error occurs during processing
+ public func finalize() throws {
+ // Do nothing if already finalized
+ if _finalized { return }
+
+ // Finalize stream
+ _stream.src_size = 0
+ var status = COMPRESSION_STATUS_OK
+ while (status != COMPRESSION_STATUS_END) { status = try process(finalizing: true) }
+
+ // Update state
+ _finalized = true
+
+ // Notify end of stream
+ try _writeFunc(nil)
+ }
+
+ // Cleanup resources. The filter is finalized now if it was not finalized yet.
+ deinit {
+ // Finalize now if not done earlier
+ try? finalize()
+
+ // Cleanup
+ _buf.deallocate()
+ compression_stream_destroy(&_stream)
+ }
+
+ // Call compression_stream_process with current src, and dst set to _buf, then write output to the closure
+ // Return status
+ private func process(finalizing finalize: Bool) throws -> compression_status {
+ // Process current input, and write to buf
+ _stream.dst_ptr = _buf
+ _stream.dst_size = _bufCapacity
+
+ let status = compression_stream_process(&_stream, (finalize ? Int32(COMPRESSION_STREAM_FINALIZE.rawValue) : 0))
+ guard status != COMPRESSION_STATUS_ERROR else { throw FilterError.filterProcessError }
+
+ // Number of bytes written to buf
+ let writtenBytes = _bufCapacity - _stream.dst_size
+
+ // Write output
+ if writtenBytes > 0 {
+ let outData = Data(bytesNoCopy: _buf, count: writtenBytes, deallocator: .none)
+ try _writeFunc(outData)
+ }
+
+ return status
+ }
+
+}
+
+@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+public class InputFilter {
+ private var _stream: compression_stream
+ private var _buf: Data? = nil // current input data
+ private let _bufCapacity: Int // size to read when refilling _buf
+ private let _readFunc: (Int) throws -> Data?
+ private var _eofReached: Bool = false // did we read end-of-file from the input?
+ private var _endReached: Bool = false // did we reach end-of-file from the decoder stream?
+
+ /// Initialize an input filter
+ ///
+ /// - Parameters:
+ /// - operation: direction of operation
+ /// - algorithm: compression algorithm
+ /// - bufferCapacity: capacity of the internal data buffer
+ /// - readFunc: called to read the input data
+ ///
+ /// - Throws: `FilterError.filterInitError` if filter initialization failed
+ public init(
+ _ operation: FilterOperation,
+ using algorithm: Algorithm,
+ bufferCapacity: Int = 65536,
+ readingFrom readFunc: @escaping (Int) throws -> Data?
+ ) throws {
+ _stream = try compression_stream(operation: operation, algorithm: algorithm)
+ _bufCapacity = bufferCapacity
+ _readFunc = readFunc
+ }
+
+ /// Read processed data from the filter
+ ///
+ /// Input data, when needed, is obtained from the input closure
+ /// When the input closure returns a nil or empty Data object, the filter will be
+ /// finalized, and after all processed data has been read, readData will return nil
+ /// to signal end of input
+ ///
+ /// - Parameter count: max number of bytes to read from the filter
+ ///
+ /// - Returns: a new Data object containing at most `count` output bytes, or nil if no more data is available
+ ///
+ /// - Throws:
+ /// `FilterError.filterProcessError` if an error occurs during processing
+ public func readData(ofLength count: Int) throws -> Data? {
+ // Sanity check
+ precondition(count > 0, "number of bytes to read can't be 0")
+
+ // End reached, return early, nothing to do
+ if _endReached { return nil }
+
+ // Allocate result
+ var result = Data(count: count)
+
+ try result.withUnsafeMutableBytes { (dst_ptr: UnsafeMutablePointer<UInt8>) in
+
+ // Write to result until full, or end reached
+ _stream.dst_size = count
+ _stream.dst_ptr = dst_ptr
+
+ while _stream.dst_size > 0 && !_endReached {
+
+ // Refill _buf if needed, and EOF was not yet read
+ if _stream.src_size == 0 && !_eofReached {
+ _buf = try _readFunc(_bufCapacity) // may be nil
+ // Reset src_size to full _buf size
+ if _buf?.count ?? 0 == 0 { _eofReached = true }
+ _stream.src_size = _buf?.count ?? 0
+ }
+
+ // Process some data
+ if let buf = _buf {
+ try buf.withUnsafeBytes { (src_ptr: UnsafePointer<UInt8>) in
+
+ // Next byte to read
+ _stream.src_ptr = src_ptr + buf.count - _stream.src_size
+
+ let status = compression_stream_process(&_stream, (_eofReached ? Int32(COMPRESSION_STREAM_FINALIZE.rawValue) : 0))
+ guard status != COMPRESSION_STATUS_ERROR else { throw FilterError.filterProcessError }
+ if status == COMPRESSION_STATUS_END { _endReached = true }
+ }
+ }
+ else {
+ let status = compression_stream_process(&_stream, (_eofReached ? Int32(COMPRESSION_STREAM_FINALIZE.rawValue) : 0))
+ guard status != COMPRESSION_STATUS_ERROR else { throw FilterError.filterProcessError }
+ if status == COMPRESSION_STATUS_END { _endReached = true }
+
+ }
+ }
+
+ } // result.withUnsafeMutableBytes
+
+ // Update actual size
+ result.count = count - _stream.dst_size
+ return result
+ }
+
+ // Cleanup resources
+ deinit {
+ compression_stream_destroy(&_stream)
+ }
+
+}
diff --git a/stdlib/public/Darwin/Foundation/JSONEncoder.swift b/stdlib/public/Darwin/Foundation/JSONEncoder.swift
index e5811a0..d871160 100644
--- a/stdlib/public/Darwin/Foundation/JSONEncoder.swift
+++ b/stdlib/public/Darwin/Foundation/JSONEncoder.swift
@@ -53,9 +53,9 @@
/// `JSONEncoder` facilitates the encoding of `Encodable` values into JSON.
// NOTE: older overlays had Foundation.JSONEncoder as the ObjC name.
// The two must coexist, so it was renamed. The old name must not be
-// used in the new runtime. _TtC10Foundation12_JSONEncoder is the
-// mangled name for Foundation._JSONEncoder.
-@_objcRuntimeName(_TtC10Foundation12_JSONEncoder)
+// used in the new runtime. _TtC10Foundation13__JSONEncoder is the
+// mangled name for Foundation.__JSONEncoder.
+@_objcRuntimeName(_TtC10Foundation13__JSONEncoder)
open class JSONEncoder {
// MARK: Options
@@ -1017,9 +1017,9 @@
/// `JSONDecoder` facilitates the decoding of JSON into semantic `Decodable` types.
// NOTE: older overlays had Foundation.JSONDecoder as the ObjC name.
// The two must coexist, so it was renamed. The old name must not be
-// used in the new runtime. _TtC10Foundation12_JSONDecoder is the
-// mangled name for Foundation._JSONDecoder.
-@_objcRuntimeName(_TtC10Foundation12_JSONDecoder)
+// used in the new runtime. _TtC10Foundation13__JSONDecoder is the
+// mangled name for Foundation.__JSONDecoder.
+@_objcRuntimeName(_TtC10Foundation13__JSONDecoder)
open class JSONDecoder {
// MARK: Options
@@ -1190,7 +1190,7 @@
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
}
- let decoder = _JSONDecoder(referencing: topLevel, options: self.options)
+ let decoder = __JSONDecoder(referencing: topLevel, options: self.options)
guard let value = try decoder.unbox(topLevel, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
@@ -1199,9 +1199,12 @@
}
}
-// MARK: - _JSONDecoder
+// MARK: - __JSONDecoder
-fileprivate class _JSONDecoder : Decoder {
+// NOTE: older overlays called this class _JSONDecoder. The two must
+// coexist without a conflicting ObjC class name, so it was renamed.
+// The old name must not be used in the new runtime.
+fileprivate class __JSONDecoder : Decoder {
// MARK: Properties
/// The decoder's storage.
@@ -1307,7 +1310,7 @@
// MARK: Properties
/// A reference to the decoder we're reading from.
- private let decoder: _JSONDecoder
+ private let decoder: __JSONDecoder
/// A reference to the container we're reading from.
private let container: [String : Any]
@@ -1318,7 +1321,7 @@
// MARK: - Initialization
/// Initializes `self` by referencing the given decoder and container.
- fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [String : Any]) {
+ fileprivate init(referencing decoder: __JSONDecoder, wrapping container: [String : Any]) {
self.decoder = decoder
switch decoder.options.keyDecodingStrategy {
case .useDefaultKeys:
@@ -1637,7 +1640,7 @@
defer { self.decoder.codingPath.removeLast() }
let value: Any = self.container[key.stringValue] ?? NSNull()
- return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
+ return __JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
}
public func superDecoder() throws -> Decoder {
@@ -1653,7 +1656,7 @@
// MARK: Properties
/// A reference to the decoder we're reading from.
- private let decoder: _JSONDecoder
+ private let decoder: __JSONDecoder
/// A reference to the container we're reading from.
private let container: [Any]
@@ -1667,7 +1670,7 @@
// MARK: - Initialization
/// Initializes `self` by referencing the given decoder and container.
- fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [Any]) {
+ fileprivate init(referencing decoder: __JSONDecoder, wrapping container: [Any]) {
self.decoder = decoder
self.container = container
self.codingPath = decoder.codingPath
@@ -2000,11 +2003,11 @@
let value = self.container[self.currentIndex]
self.currentIndex += 1
- return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
+ return __JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
}
}
-extension _JSONDecoder : SingleValueDecodingContainer {
+extension __JSONDecoder : SingleValueDecodingContainer {
// MARK: SingleValueDecodingContainer Methods
private func expectNonNull<T>(_ type: T.Type) throws {
@@ -2095,7 +2098,7 @@
// MARK: - Concrete Value Representations
-extension _JSONDecoder {
+extension __JSONDecoder {
/// Returns the given value unboxed from a container.
fileprivate func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
guard !(value is NSNull) else { return nil }
diff --git a/stdlib/public/SwiftShims/SwiftStddef.h b/stdlib/public/SwiftShims/SwiftStddef.h
index eb7df54..ab6f9dc 100644
--- a/stdlib/public/SwiftShims/SwiftStddef.h
+++ b/stdlib/public/SwiftShims/SwiftStddef.h
@@ -29,11 +29,18 @@
#endif
// This selects the signed equivalent of the unsigned type chosen for size_t.
+#if __STDC_VERSION__-0 >= 201112l
typedef __typeof__(_Generic((__swift_size_t)0, \
unsigned long long int : (long long int)0, \
unsigned long int : (long int)0, \
unsigned int : (int)0, \
unsigned short : (short)0, \
unsigned char : (signed char)0)) __swift_ssize_t;
+#elif defined(__cplusplus)
+#include <type_traits>
+using __swift_ssize_t = std::make_signed<__swift_size_t>::type;
+#else
+#error "do not have __swift_ssize_t defined"
+#endif
#endif // SWIFT_STDLIB_SHIMS_SWIFT_STDDEF_H
diff --git a/stdlib/public/core/AtomicInt.swift.gyb b/stdlib/public/core/AtomicInt.swift.gyb
index 17d3484..62217f2 100644
--- a/stdlib/public/core/AtomicInt.swift.gyb
+++ b/stdlib/public/core/AtomicInt.swift.gyb
@@ -10,7 +10,12 @@
//
//===----------------------------------------------------------------------===//
+// NOTE: older runtimes had Swift._stdlib_AtomicInt as the ObjC name.
+// The two must coexist, so it was renamed. The old name must not be
+// used in the new runtime. _TtCs18__stdlib_AtomicInt is the mangled
+// name for Swift.__stdlib_AtomicInt
@available(swift, deprecated: 4.2, obsoleted: 5.0)
+@_objcRuntimeName(_TtCs18__stdlib_AtomicInt)
public final class _stdlib_AtomicInt {
internal var _value: Int
diff --git a/stdlib/public/core/Builtin.swift b/stdlib/public/core/Builtin.swift
index 761df17..01b9e89 100644
--- a/stdlib/public/core/Builtin.swift
+++ b/stdlib/public/core/Builtin.swift
@@ -668,9 +668,6 @@
return Bool(Builtin.isUnique(&object))
}
-@_silgen_name("_swift_reallocObject")
-internal func _reallocObject(_ object: UnsafeMutableRawPointer, _ newSizeInBytes: Int) -> UnsafeMutableRawPointer?
-
/// Returns `true` if `object` is uniquely referenced.
/// This provides sanity checks on top of the Builtin.
@_transparent
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index 1468ab8..db1b1ff 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -433,6 +433,7 @@
/// An equivalent range must be representable as a closed range.
/// For example, passing an empty range as `other` triggers a runtime error,
/// because an empty range cannot be represented by a closed range instance.
+ @inlinable
public init(_ other: Range<Bound>) {
_precondition(!other.isEmpty, "Can't form an empty closed range")
let upperBound = other.upperBound.advanced(by: -1)
diff --git a/stdlib/public/core/ManagedBuffer.swift b/stdlib/public/core/ManagedBuffer.swift
index ab5b74c..67c0a8d 100644
--- a/stdlib/public/core/ManagedBuffer.swift
+++ b/stdlib/public/core/ManagedBuffer.swift
@@ -136,30 +136,6 @@
}
}
-@inline(never)
-public func tryReallocateUniquelyReferenced<Header, Element, Buffer: ManagedBuffer<Header, Element>>(
- buffer: inout Buffer,
- newMinimumCapacity: Int
-) -> Bool {
- precondition(_isBitwiseTakable(Header.self))
- precondition(_isBitwiseTakable(Element.self))
- precondition(isKnownUniquelyReferenced(&buffer))
-
- let newSizeInBytes = MemoryLayout<Header>.stride
- + newMinimumCapacity * MemoryLayout<Element>.stride
-
- return withUnsafeMutablePointer(to: &buffer) {
- $0.withMemoryRebound(to: UnsafeMutableRawPointer.self, capacity: 1) {
- if let reallocdObject = _reallocObject($0.pointee, newSizeInBytes) {
- $0.pointee = reallocdObject
- return true
- } else {
- return false
- }
- }
- }
-}
-
/// Contains a buffer object, and provides access to an instance of
/// `Header` and contiguous storage for an arbitrary number of
/// `Element` instances stored in that buffer.
diff --git a/stdlib/public/core/StringStorage.swift b/stdlib/public/core/StringStorage.swift
index d6f2694..a8480ac 100644
--- a/stdlib/public/core/StringStorage.swift
+++ b/stdlib/public/core/StringStorage.swift
@@ -76,9 +76,8 @@
fallthrough
case (_cocoaUTF8Encoding, _):
guard maxLength >= count + 1 else { return 0 }
- let buffer = UnsafeMutableBufferPointer(start: outputPtr, count: maxLength)
- _ = buffer.initialize(from: UnsafeBufferPointer(start: start, count: count))
- buffer[count] = 0
+ outputPtr.initialize(from: start, count: count)
+ outputPtr[count] = 0
return 1
default:
return _cocoaGetCStringTrampoline(self, outputPtr, maxLength, encoding)
diff --git a/stdlib/public/runtime/SwiftObject.h b/stdlib/public/runtime/SwiftObject.h
index 10e6d68..a730d51 100644
--- a/stdlib/public/runtime/SwiftObject.h
+++ b/stdlib/public/runtime/SwiftObject.h
@@ -88,11 +88,4 @@
#endif
-namespace swift {
-
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_SPI
-HeapObject *_swift_reallocObject(HeapObject *obj, size_t size);
-
-}
-
#endif
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index 5ed874c..9c6dfbe 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -82,24 +82,6 @@
#endif
}
-bool isObjCPinned(HeapObject *obj) {
- #if SWIFT_OBJC_INTEROP
- /* future: implement checking the relevant objc runtime bits */
- return true;
- #else
- return false;
- #endif
-}
-
-// returns non-null if realloc was successful
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_SPI
-HeapObject *swift::_swift_reallocObject(HeapObject *obj, size_t size) {
- if (isObjCPinned(obj) || obj->refCounts.hasSideTable()) {
- return nullptr;
- }
- return (HeapObject *)realloc(obj, size);
-}
-
#if SWIFT_OBJC_INTEROP
/// Replacement for ObjC object_isClass(), which is unavailable on
diff --git a/test/APINotes/Inputs/roundtrip.apinotes b/test/APINotes/Inputs/roundtrip.apinotes
deleted file mode 100644
index 9435acf..0000000
--- a/test/APINotes/Inputs/roundtrip.apinotes
+++ /dev/null
@@ -1,79 +0,0 @@
----
-Name: AppKit
-Availability: available
-AvailabilityMsg: ''
-Classes:
- - Name: NSCell
- Availability: available
- AvailabilityMsg: ''
- Methods:
- - Selector: init
- MethodKind: Instance
- NullabilityOfRet: U
- Availability: available
- AvailabilityMsg: ''
- DesignatedInit: true
- - Selector: 'initImageCell:'
- MethodKind: Instance
- Nullability: [ N ]
- NullabilityOfRet: U
- Availability: available
- AvailabilityMsg: ''
- DesignatedInit: true
- - Selector: 'initTextCell:'
- MethodKind: Instance
- Nullability: [ N ]
- NullabilityOfRet: U
- Availability: available
- AvailabilityMsg: ''
- DesignatedInit: true
- - Selector: 'initWithCoder:'
- MethodKind: Instance
- Nullability: [ N ]
- NullabilityOfRet: U
- Availability: available
- AvailabilityMsg: ''
- DesignatedInit: true
- Required: true
- - Name: NSView
- AuditedForNullability: true
- Availability: available
- AvailabilityMsg: ''
- Methods:
- - Selector: 'addSubview:'
- MethodKind: Instance
- Nullability: [ N ]
- NullabilityOfRet: N
- Availability: available
- AvailabilityMsg: ''
- - Selector: 'addSubview:positioned:relativeTo:'
- MethodKind: Instance
- Nullability: [ N, N, O ]
- NullabilityOfRet: N
- Availability: available
- AvailabilityMsg: ''
- - Selector: 'beginDraggingSessionWithItems:event:source:'
- MethodKind: Instance
- Nullability: [ U, U, N ]
- NullabilityOfRet: N
- Availability: available
- AvailabilityMsg: ''
- Properties:
- - Name: enclosingScrollView
- Nullability: O
- Availability: available
- AvailabilityMsg: ''
- - Name: makeBackingLayer
- Nullability: N
- Availability: available
- AvailabilityMsg: ''
-Functions:
- - Name: NSAvailableWindowDepths
- NullabilityOfRet: N
- Availability: available
- AvailabilityMsg: ''
-Globals:
- - Name: NSCalibratedWhiteColorSpace
- Nullability: N
- Availability: available
- AvailabilityMsg: ''
diff --git a/test/APINotes/yaml-roundtrip.swift b/test/APINotes/yaml-roundtrip.swift
deleted file mode 100644
index f2a3ada..0000000
--- a/test/APINotes/yaml-roundtrip.swift
+++ /dev/null
@@ -1,7 +0,0 @@
-# RUN: %swift_driver_plain -apinotes -yaml-to-binary -o %t.apinotesc %S/Inputs/roundtrip.apinotes
-# RUN: %swift_driver_plain -apinotes -binary-to-yaml -o %t.apinotes %t.apinotesc
-
-# Note: We don't diff the results because they will change as Clang's
-# API notes support evolves, and we don't want to tie that closely to
-# a specific Clang.
-
diff --git a/test/CircularReferences/protocols.swift b/test/CircularReferences/protocols.swift
new file mode 100644
index 0000000..d071907
--- /dev/null
+++ b/test/CircularReferences/protocols.swift
@@ -0,0 +1,12 @@
+// RUN: %target-typecheck-verify-swift -debug-cycles 2>&1 | %FileCheck --allow-empty %s
+
+// Verify that protocol where clause lookups don't cause cyclic dependencies.
+
+// expected-no-diagnostics
+
+class C { }
+protocol Q { }
+protocol P where Self : Q, Self : C { }
+
+// CHECK-NOT: CYCLE DETECTED
+
diff --git a/test/ClangImporter/Inputs/app-bridging-header-to-pch.h b/test/ClangImporter/Inputs/app-bridging-header-to-pch.h
index f8d56b7..c6fb28d 100644
--- a/test/ClangImporter/Inputs/app-bridging-header-to-pch.h
+++ b/test/ClangImporter/Inputs/app-bridging-header-to-pch.h
@@ -1,3 +1,10 @@
+
+#ifndef app_bridging_header_to_pch_h
+#define app_bridging_header_to_pch_h
+
static inline int app_function(int x) {
return x + 27;
}
+
+#endif
+
diff --git a/test/ClangImporter/Inputs/chained-unit-test-bridging-header-to-pch.h b/test/ClangImporter/Inputs/chained-unit-test-bridging-header-to-pch.h
index c027342..810736b 100644
--- a/test/ClangImporter/Inputs/chained-unit-test-bridging-header-to-pch.h
+++ b/test/ClangImporter/Inputs/chained-unit-test-bridging-header-to-pch.h
@@ -1,5 +1,12 @@
+
+#ifndef chained_unit_test_bridging_header_to_pch_h
+#define chained_unit_test_bridging_header_to_pch_h
+
#include "app-bridging-header-to-pch.h"
static inline int unit_test_function(int x) {
return x + 28;
}
+
+#endif
+
diff --git a/test/ClangImporter/cfuncs_parse.swift b/test/ClangImporter/cfuncs_parse.swift
index e5e2cb1..ba91c59 100644
--- a/test/ClangImporter/cfuncs_parse.swift
+++ b/test/ClangImporter/cfuncs_parse.swift
@@ -1,3 +1,4 @@
+// XFAIL: CPU=powerpc64le
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -I %S/Inputs %s
import cfuncs
diff --git a/test/ClangImporter/inlinable_bitfields.swift b/test/ClangImporter/inlinable_bitfields.swift
index ea417b6..be6ede2 100644
--- a/test/ClangImporter/inlinable_bitfields.swift
+++ b/test/ClangImporter/inlinable_bitfields.swift
@@ -10,4 +10,4 @@
// Just make sure this is a definition and not a declaration...
-// CHECK: define internal i32 @"$ModRM$rm$getter"
+// CHECK: define internal{{( zeroext)?}} i32 @"$ModRM$rm$getter"
diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift
index 4a10050..971d721 100644
--- a/test/Constraints/diagnostics.swift
+++ b/test/Constraints/diagnostics.swift
@@ -659,7 +659,7 @@
struct UnaryOp {}
_ = -UnaryOp() // expected-error {{unary operator '-' cannot be applied to an operand of type 'UnaryOp'}}
-// expected-note@-1 {{overloads for '-' exist with these partially matching parameter lists: (Double), (Float), (Float80)}}
+// expected-note@-1 {{overloads for '-' exist with these partially matching parameter lists: (Double), (Float)}}
// <rdar://problem/23433271> Swift compiler segfault in failure diagnosis
diff --git a/test/Constraints/sr9626.swift b/test/Constraints/sr9626.swift
new file mode 100644
index 0000000..049951b
--- /dev/null
+++ b/test/Constraints/sr9626.swift
@@ -0,0 +1,22 @@
+// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
+
+class BaseClass {}
+class SubClass: BaseClass {}
+struct Box<T> { init(_: T.Type) {} }
+
+
+func test1<T>(box: Box<T>) -> T.Type {
+ return T.self
+}
+
+func test2<T: BaseClass>(box: Box<T>) -> T.Type {
+ return T.self
+}
+
+// CHECK: [[F1:%.*]] = function_ref @$s6sr96263BoxVyACyxGxmcfC
+// CHECK-NEXT: apply [[F1]]<SubClass>({{.*}}, {{.*}})
+_ = test1(box: .init(SubClass.self))
+
+// CHECK: [[F2:%.*]] = function_ref @$s6sr96265test23boxxmAA3BoxVyxG_tAA9BaseClassCRbzlF
+// CHECK-NEXT: apply [[F2]]<SubClass>({{.*}})
+_ = test2(box: .init(SubClass.self))
diff --git a/test/Driver/fuzzer.swift b/test/Driver/fuzzer.swift
index 3903892..d83fad2 100644
--- a/test/Driver/fuzzer.swift
+++ b/test/Driver/fuzzer.swift
@@ -1,4 +1,5 @@
// UNSUPPORTED: win32
+// UNSUPPORTED: CPU=powerpc64le
// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=LIBFUZZER %s
// LIBFUZZER: libclang_rt.fuzzer
diff --git a/test/IDE/clang-importing/Inputs/bridge.h b/test/IDE/clang-importing/Inputs/bridge.h
index 920e7aa..77a08a9 100644
--- a/test/IDE/clang-importing/Inputs/bridge.h
+++ b/test/IDE/clang-importing/Inputs/bridge.h
@@ -1 +1,4 @@
+@import Foundation;
@import somemod1;
+
+void func_in_bridge(void);
diff --git a/test/IDE/clang-importing/complete_with_clang_comments.swift b/test/IDE/clang-importing/complete_with_clang_comments.swift
index dfa17fa..b3816c0 100644
--- a/test/IDE/clang-importing/complete_with_clang_comments.swift
+++ b/test/IDE/clang-importing/complete_with_clang_comments.swift
@@ -1,5 +1,7 @@
-// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP -code-completion-comments=true \
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP -code-completion-comments=true \
// RUN: -import-objc-header %S/Inputs/bridge.h -I %S/Inputs/somemod1 -I %S/Inputs/somemod2 | %FileCheck %s -check-prefix=CHECK-TOP
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP -code-completion-comments=true \
+// RUN: -import-objc-header %S/Inputs/bridge.h -pch-output-dir %t.pch -I %S/Inputs/somemod1 -I %S/Inputs/somemod2 | %FileCheck %s -check-prefix=CHECK-TOP
// REQUIRES: objc_interop
diff --git a/test/IDE/print_ast_overlay.swift b/test/IDE/print_ast_overlay.swift
index 7a60b6c..53233c4 100644
--- a/test/IDE/print_ast_overlay.swift
+++ b/test/IDE/print_ast_overlay.swift
@@ -1,17 +1,16 @@
// RUN: %empty-directory(%t)
-// RUN: %target-build-swift -emit-module -module-name Foo -o %t -F %S/Inputs/mock-sdk %s
+// RUN: %target-build-swift -emit-module -module-name Foo -o %t -F %S/Inputs/mock-sdk %s -Xfrontend -enable-objc-interop -Xfrontend -disable-objc-attr-requires-foundation-module
//
-// RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo -access-filter-public > %t.printed.txt
+// RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo -access-filter-public -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_WITH_OVERLAY -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_NO_INTERNAL -strict-whitespace < %t.printed.txt
//
-// RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo.FooSub > %t.printed.txt
+// RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo.FooSub -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_WITHOUT_OVERLAY -strict-whitespace < %t.printed.txt
-// XFAIL: linux, freebsd
-
-// RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo -access-filter-public -annotate-print > %t.annotated.txt
+// RUN: %target-swift-ide-test -print-module -source-filename %s -I %t -F %S/Inputs/mock-sdk -module-to-print=Foo -access-filter-public -annotate-print -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.annotated.txt
// RUN: %FileCheck %s -check-prefix=PASS_ANNOTATED -strict-whitespace < %t.annotated.txt
+
// REQUIRES: executable_test
@_exported import Foo
diff --git a/test/IDE/print_ast_tc_decls.swift b/test/IDE/print_ast_tc_decls.swift
index 147fbc5..6fc4589 100644
--- a/test/IDE/print_ast_tc_decls.swift
+++ b/test/IDE/print_ast_tc_decls.swift
@@ -1,16 +1,16 @@
// RUN: %empty-directory(%t)
//
// Build swift modules this test depends on.
-// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/foo_swift_module.swift
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/foo_swift_module.swift -enable-objc-interop -disable-objc-attr-requires-foundation-module
//
// FIXME: BEGIN -enable-source-import hackaround
-// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift -enable-objc-interop -disable-objc-attr-requires-foundation-module
// FIXME: END -enable-source-import hackaround
//
// This file should not have any syntax or type checker errors.
-// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -typecheck -verify %s -F %S/Inputs/mock-sdk -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -typecheck -verify %s -F %S/Inputs/mock-sdk -enable-objc-interop -disable-objc-attr-requires-foundation-module
//
-// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -skip-deinit=false -print-ast-typechecked -source-filename %s -F %S/Inputs/mock-sdk -function-definitions=false -prefer-type-repr=false -print-implicit-attrs=true -disable-objc-attr-requires-foundation-module > %t.printed.txt
+// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -skip-deinit=false -print-ast-typechecked -source-filename %s -F %S/Inputs/mock-sdk -function-definitions=false -prefer-type-repr=false -print-implicit-attrs=true -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_COMMON -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_PRINT_AST -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_RW_PROP_GET_SET -strict-whitespace < %t.printed.txt
@@ -21,7 +21,7 @@
// RUN: %FileCheck %s -check-prefix=PREFER_TYPE_PRINTING -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_QUAL_UNQUAL -strict-whitespace < %t.printed.txt
//
-// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -skip-deinit=false -print-ast-typechecked -source-filename %s -F %S/Inputs/mock-sdk -function-definitions=false -prefer-type-repr=true -print-implicit-attrs=true -disable-objc-attr-requires-foundation-module > %t.printed.txt
+// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -skip-deinit=false -print-ast-typechecked -source-filename %s -F %S/Inputs/mock-sdk -function-definitions=false -prefer-type-repr=true -print-implicit-attrs=true -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_COMMON -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_PRINT_AST -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_RW_PROP_GET_SET -strict-whitespace < %t.printed.txt
@@ -32,8 +32,8 @@
// RUN: %FileCheck %s -check-prefix=PREFER_TYPE_REPR_PRINTING -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_QUAL_UNQUAL -strict-whitespace < %t.printed.txt
//
-// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -emit-module -o %t -F %S/Inputs/mock-sdk -disable-objc-attr-requires-foundation-module %s
-// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -skip-deinit=false -print-module -source-filename %s -F %S/Inputs/mock-sdk -module-to-print=print_ast_tc_decls -print-implicit-attrs=true -disable-objc-attr-requires-foundation-module > %t.printed.txt
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -emit-module -o %t -F %S/Inputs/mock-sdk -enable-objc-interop -disable-objc-attr-requires-foundation-module %s
+// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -swift-version 4 -skip-deinit=false -print-module -source-filename %s -F %S/Inputs/mock-sdk -module-to-print=print_ast_tc_decls -print-implicit-attrs=true -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_COMMON -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_PRINT_MODULE_INTERFACE -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_RW_PROP_NO_GET_SET -strict-whitespace < %t.printed.txt
@@ -45,20 +45,20 @@
// RUN: %FileCheck %s -check-prefix=PASS_QUAL_UNQUAL -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_EXPLODE_PATTERN -strict-whitespace < %t.printed.txt
//
-// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -skip-deinit=false -print-module -source-filename %s -F %S/Inputs/mock-sdk -I %t -module-to-print=print_ast_tc_decls -synthesize-sugar-on-types=true -print-implicit-attrs=true -disable-objc-attr-requires-foundation-module > %t.printed.txt
+// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -skip-deinit=false -print-module -source-filename %s -F %S/Inputs/mock-sdk -I %t -module-to-print=print_ast_tc_decls -synthesize-sugar-on-types=true -print-implicit-attrs=true -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_PRINT_MODULE_INTERFACE -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_QUAL_UNQUAL -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=SYNTHESIZE_SUGAR_ON_TYPES -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_EXPLODE_PATTERN -strict-whitespace < %t.printed.txt
-// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -skip-deinit=false -print-module -source-filename %s -F %S/Inputs/mock-sdk -I %t -module-to-print=print_ast_tc_decls -synthesize-sugar-on-types=true -fully-qualified-types-if-ambiguous=true -print-implicit-attrs=true -disable-objc-attr-requires-foundation-module > %t.printed.txt
+// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -skip-deinit=false -print-module -source-filename %s -F %S/Inputs/mock-sdk -I %t -module-to-print=print_ast_tc_decls -synthesize-sugar-on-types=true -fully-qualified-types-if-ambiguous=true -print-implicit-attrs=true -enable-objc-interop -disable-objc-attr-requires-foundation-module > %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_PRINT_MODULE_INTERFACE -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=PASS_QUAL_IF_AMBIGUOUS -strict-whitespace < %t.printed.txt
// RUN: %FileCheck %s -check-prefix=SYNTHESIZE_SUGAR_ON_TYPES -strict-whitespace < %t.printed.txt
// FIXME: %FileCheck %s -check-prefix=PASS_EXPLODE_PATTERN -strict-whitespace < %t.printed.txt
// FIXME: rdar://problem/19648117 Needs splitting objc parts out
-// XFAIL: linux, freebsd
+// REQUIRES: objc_interop
import Bar
import ObjectiveC
diff --git a/test/IDE/print_ast_typechecked.swift b/test/IDE/print_ast_typechecked.swift
index 3b20e5d..e5200f0 100644
--- a/test/IDE/print_ast_typechecked.swift
+++ b/test/IDE/print_ast_typechecked.swift
@@ -15,3 +15,6 @@
// CHECK1: {{^}} var InternalVar1: Int, InternalVar2: Int{{$}}
// CHECK1-NOT: private
// CHECK1: {{^}} var (InternalTuple1, InternalTuple2): (Int, Int){{$}}
+
+// RUN: %target-swift-ide-test -fully-qualified-types -print-ast-typechecked -access-filter-internal -source-filename %s | %FileCheck %s -check-prefix=FULLY_QUAL
+// FULLY_QUAL: public var PublicVar: Swift.Int
diff --git a/test/IDE/print_clang_decls.swift b/test/IDE/print_clang_decls.swift
index ce984e4..ecc6a8f 100644
--- a/test/IDE/print_clang_decls.swift
+++ b/test/IDE/print_clang_decls.swift
@@ -1,12 +1,12 @@
// RUN: %empty-directory(%t)
-// XFAIL: linux, freebsd
+// REQUIRES: objc_interop
// This file deliberately does not use %clang-importer-sdk for most RUN lines.
// Instead, it generates custom overlay modules itself, and uses -I %t when it
// wants to use them.
-// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift -enable-objc-interop -disable-objc-attr-requires-foundation-module
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk -I %t) -emit-module -o %t %S/../Inputs/clang-importer-sdk/swift-modules/Foundation.swift
// RUN: %target-swift-ide-test(mock-sdk: -sdk %S/../Inputs/clang-importer-sdk -I %t) -print-module -source-filename %s -module-to-print=ctypes -function-definitions=false -prefer-type-repr=true > %t.printed.txt
diff --git a/test/IDE/print_clang_header.swift b/test/IDE/print_clang_header.swift
index 2faccf8..8ad2cdf 100644
--- a/test/IDE/print_clang_header.swift
+++ b/test/IDE/print_clang_header.swift
@@ -1,25 +1,25 @@
// FIXME: rdar://problem/19648117 Needs splitting objc parts out
-// XFAIL: linux, freebsd
+// REQUIRES: objc_interop
// RUN: echo '#include "header-to-print.h"' > %t.m
-// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.m -I %S/Inputs/print_clang_header > %t.txt
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments -enable-objc-interop -disable-objc-attr-requires-foundation-module --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.m -I %S/Inputs/print_clang_header > %t.txt
// RUN: diff -u %S/Inputs/print_clang_header/header-to-print.h.printed.txt %t.txt
// RUN: %clang %target-cc-options -isysroot %clang-importer-sdk-path -fmodules -x objective-c-header %S/Inputs/print_clang_header/header-to-print.h -o %t.h.pch
// RUN: touch %t.empty.m
-// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.empty.m -I %S/Inputs/print_clang_header -include %t.h > %t.with-pch.txt
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments -enable-objc-interop -disable-objc-attr-requires-foundation-module --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.empty.m -I %S/Inputs/print_clang_header -include %t.h > %t.with-pch.txt
// RUN: diff -u %S/Inputs/print_clang_header/header-to-print.h.command-line-include.printed.txt %t.with-pch.txt
-// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.empty.m -I %S/Inputs/print_clang_header -include %S/Inputs/print_clang_header/header-to-print.h > %t.with-include.txt
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments -enable-objc-interop -disable-objc-attr-requires-foundation-module --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.empty.m -I %S/Inputs/print_clang_header -include %S/Inputs/print_clang_header/header-to-print.h > %t.with-include.txt
// RUN: diff -u %S/Inputs/print_clang_header/header-to-print.h.command-line-include.printed.txt %t.with-include.txt
// RUN: echo '#include <Foo/header-to-print.h>' > %t.framework.m
// RUN: sed -e "s:INPUT_DIR:%S/Inputs/print_clang_header:g" -e "s:OUT_DIR:%t:g" %S/Inputs/print_clang_header/Foo-vfsoverlay.yaml > %t.yaml
-// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.framework.m -F %t -ivfsoverlay %t.yaml -Xclang -fmodule-name=Foo > %t.framework.txt
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments -enable-objc-interop -disable-objc-attr-requires-foundation-module --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.framework.m -F %t -ivfsoverlay %t.yaml -Xclang -fmodule-name=Foo > %t.framework.txt
// RUN: diff -u %S/Inputs/print_clang_header/header-to-print.h.printed.txt %t.framework.txt
// Test header interface printing from a clang module, with the preprocessing record enabled before the CC args.
-// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments -Xcc -Xclang -Xcc -detailed-preprocessing-record --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.framework.m -F %t -ivfsoverlay %t.yaml > %t.module.txt
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments -Xcc -Xclang -Xcc -detailed-preprocessing-record -enable-objc-interop -disable-objc-attr-requires-foundation-module --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.framework.m -F %t -ivfsoverlay %t.yaml > %t.module.txt
// RUN: diff -u %S/Inputs/print_clang_header/header-to-print.h.module.printed.txt %t.module.txt
// Test header interface printing from a clang module, with the preprocessing record enabled by the CC args.
-// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.framework.m -F %t -ivfsoverlay %t.yaml -Xclang -detailed-preprocessing-record > %t.module2.txt
+// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -source-filename %s -print-header -header-to-print %S/Inputs/print_clang_header/header-to-print.h -print-regular-comments -enable-objc-interop -disable-objc-attr-requires-foundation-module --cc-args %target-cc-options -isysroot %clang-importer-sdk-path -fsyntax-only %t.framework.m -F %t -ivfsoverlay %t.yaml -Xclang -detailed-preprocessing-record > %t.module2.txt
// RUN: diff -u %S/Inputs/print_clang_header/header-to-print.h.module.printed.txt %t.module2.txt
diff --git a/test/IDE/print_usrs.swift b/test/IDE/print_usrs.swift
index 10af321..50c4d91 100644
--- a/test/IDE/print_usrs.swift
+++ b/test/IDE/print_usrs.swift
@@ -1,6 +1,12 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -disable-objc-attr-requires-foundation-module -enable-objc-interop %s
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -disable-objc-attr-requires-foundation-module -enable-objc-interop -print-usrs -source-filename %s | %FileCheck %s -strict-whitespace
+#if os(Windows) && (arch(arm64) || arch(x86_64))
+typealias ObjCEnumType = Int32
+#else
+typealias ObjCEnumType = Int
+#endif
+
import macros
// CHECK: [[@LINE+1]]:8 s:14swift_ide_test1SV{{$}}
@@ -197,7 +203,7 @@
func instanceFunc1(_ a: Int) {
// CHECK: [[@LINE+1]]:16 s:14swift_ide_test10ObjCClass1C13instanceFunc1yySiF9LocalEnumL_O
- @objc enum LocalEnum : Int {
+ @objc enum LocalEnum : ObjCEnumType {
// CHECK: [[@LINE+1]]:12 s:14swift_ide_test10ObjCClass1C13instanceFunc1yySiF9LocalEnumL_O8someCaseyA2FmF
case someCase
}
@@ -240,7 +246,7 @@
}
// CHECK: [[@LINE+1]]:12 c:@M@swift_ide_test@E@ObjCEnum{{$}}
-@objc enum ObjCEnum : Int {
+@objc enum ObjCEnum : ObjCEnumType {
// CHECK: [[@LINE+1]]:8 c:@M@swift_ide_test@E@ObjCEnum@ObjCEnumAmazingCase{{$}}
case amazingCase
diff --git a/test/IRGen/Inputs/multithread_resilience_other.swift b/test/IRGen/Inputs/multithread_resilience_other.swift
new file mode 100644
index 0000000..c76e041
--- /dev/null
+++ b/test/IRGen/Inputs/multithread_resilience_other.swift
@@ -0,0 +1,3 @@
+extension Defaultable {
+ public func defaulted() {}
+}
diff --git a/test/IRGen/big_types_corner_cases.swift b/test/IRGen/big_types_corner_cases.swift
index 759573f..ef49f6c 100644
--- a/test/IRGen/big_types_corner_cases.swift
+++ b/test/IRGen/big_types_corner_cases.swift
@@ -1,4 +1,4 @@
-
+// XFAIL: CPU=powerpc64le
// RUN: %target-swift-frontend -enable-large-loadable-types %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
// REQUIRES: optimized_stdlib
diff --git a/test/IRGen/big_types_tests.sil b/test/IRGen/big_types_tests.sil
index 1925601..f956e07 100644
--- a/test/IRGen/big_types_tests.sil
+++ b/test/IRGen/big_types_tests.sil
@@ -1,9 +1,9 @@
-// RUN: %target-swift-frontend -I %S/Inputs/abi %s -emit-ir -enable-large-loadable-types | %FileCheck %s
+// RUN: %target-swift-frontend -I %S/Inputs/abi %s -emit-ir -enable-large-loadable-types -sil-verify-all | %FileCheck %s
// REQUIRES: CPU=x86_64
// REQUIRES: OS=macosx
-sil_stage canonical
+sil_stage lowered
import Builtin
import Swift
@@ -29,3 +29,16 @@
%ret = tuple ()
return %ret : $()
}
+
+sil @capture : $@convention(thin) (@guaranteed BigStruct, Builtin.Int1) -> ()
+
+sil @test_partial_apply_stack : $@convention(thin) (@owned BigStruct, Builtin.Int1) -> () {
+entry(%x : $BigStruct, %i : $Builtin.Int1):
+ %f = function_ref @capture : $@convention(thin) (@guaranteed BigStruct, Builtin.Int1) -> ()
+ %p = partial_apply [callee_guaranteed] [on_stack] %f(%i) : $@convention(thin) (@guaranteed BigStruct, Builtin.Int1) -> ()
+ %m = mark_dependence %p : $@noescape @callee_guaranteed (@guaranteed BigStruct) -> () on %x : $BigStruct
+ %c = convert_function %m : $@noescape @callee_guaranteed (@guaranteed BigStruct) -> () to $@noescape @callee_guaranteed (@guaranteed BigStruct) -> (@error Error)
+ dealloc_stack %p : $@noescape @callee_guaranteed (@guaranteed BigStruct) -> ()
+ %ret = tuple ()
+ return %ret : $()
+}
diff --git a/test/IRGen/clang_inline_opt.swift b/test/IRGen/clang_inline_opt.swift
index db79880..4bde0f1 100644
--- a/test/IRGen/clang_inline_opt.swift
+++ b/test/IRGen/clang_inline_opt.swift
@@ -7,7 +7,7 @@
// Sanity check that we tell Clang to generate optimizable code when
// we're optimizing.
-// CHECK: define internal i32 @return7() [[CLANG_ATTRS:#[0-9]+]] {
+// CHECK: define internal{{( zeroext)?}} i32 @return7() [[CLANG_ATTRS:#[0-9]+]] {
// CHECK: attributes [[CLANG_ATTRS]] = {
// CHECK-NOT: noinline
diff --git a/test/IRGen/class_resilience_objc.swift b/test/IRGen/class_resilience_objc.swift
index 236ecbc..a6a5ce4 100644
--- a/test/IRGen/class_resilience_objc.swift
+++ b/test/IRGen/class_resilience_objc.swift
@@ -1,6 +1,7 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -emit-ir -o - -primary-file %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
// XFAIL: CPU=armv7k
+// XFAIL: CPU=powerpc64le
// CHECK: %swift.type = type { [[INT:i32|i64]] }
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index 2975d77..2b576ee8 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -252,7 +252,8 @@
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s15enum_resilience25resilientEnumPartialApplyyySi0c1_A06MediumOXEF"(i8*, %swift.opaque*)
public func resilientEnumPartialApply(_ f: (Medium) -> Int) {
-// CHECK: [[CONTEXT:%.*]] = call noalias %swift.refcounted* @swift_allocObject
+// CHECK: [[STACKALLOC:%.*]] = alloca i8
+// CHECK: [[CONTEXT:%.*]] = bitcast i8* [[STACKALLOC]] to %swift.opaque*
// CHECK: call swiftcc void @"$s15enum_resilience13reabstractionyyx010resilient_A06MediumOXElF"(i8* bitcast (void (%TSi*, %swift.opaque*, %swift.refcounted*)* @"$s14resilient_enum6MediumOSiIgnd_ACSiIegnr_TRTA" to i8*), %swift.opaque* [[CONTEXT:%.*]], %swift.type* @"$sSiN")
reabstraction(f)
diff --git a/test/IRGen/errors.sil b/test/IRGen/errors.sil
index a2b21c6..f393b0a 100644
--- a/test/IRGen/errors.sil
+++ b/test/IRGen/errors.sil
@@ -1,3 +1,4 @@
+// XFAIL: CPU=powerpc64le
// RUN: %target-swift-frontend -primary-file %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime --check-prefix=CHECK-%target-cpu
sil_stage canonical
diff --git a/test/IRGen/multithread_resilience.swift b/test/IRGen/multithread_resilience.swift
new file mode 100644
index 0000000..13c6b56
--- /dev/null
+++ b/test/IRGen/multithread_resilience.swift
@@ -0,0 +1,9 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience
+// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience -enable-testing
+// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience -enable-resilience
+// RUN: %target-swift-frontend -c %S/Inputs/multithread_resilience_other.swift %s -num-threads 2 -o %t/1.o -o %t/2.o -module-name multithread_resilience -enable-testing -enable-resilience
+
+public protocol Defaultable {
+ func defaulted()
+}
diff --git a/test/IRGen/objc_bridge.swift b/test/IRGen/objc_bridge.swift
index 12fb2e8..6425f31 100644
--- a/test/IRGen/objc_bridge.swift
+++ b/test/IRGen/objc_bridge.swift
@@ -100,7 +100,7 @@
// CHECK: @_PROPERTIES__TtC11objc_bridge3Bas = private constant { i32, i32, [5 x { i8*, i8* }] } {
-// CHECK: [[OBJC_BLOCK_PROPERTY:@.*]] = private unnamed_addr constant [11 x i8] c"T@?,N,C,Vx\00"
+// CHECK: [[OBJC_BLOCK_PROPERTY:@.*]] = private unnamed_addr constant [8 x i8] c"T@?,N,C\00"
// CHECK: @_PROPERTIES__TtC11objc_bridge21OptionalBlockProperty = private constant {{.*}} [[OBJC_BLOCK_PROPERTY]]
func getDescription(_ o: NSObject) -> String {
diff --git a/test/IRGen/objc_property_attrs.swift b/test/IRGen/objc_property_attrs.swift
index c39824b..c9934cb 100644
--- a/test/IRGen/objc_property_attrs.swift
+++ b/test/IRGen/objc_property_attrs.swift
@@ -50,11 +50,11 @@
// -- Bridged value types
- // nonatomic, copy, ivar k
- // CHECK: private unnamed_addr constant {{.*}} c"T@\22NSString\22,N,C,Vk\00"
+ // nonatomic, copy
+ // CHECK: private unnamed_addr constant {{.*}} c"T@\22NSString\22,N,C\00"
@objc var k: String = ""
- // nonatomic, readonly, ivar l
- // CHECK: private unnamed_addr constant {{.*}} c"T@\22NSString\22,N,R,Vl\00"
+ // nonatomic, readonly
+ // CHECK: private unnamed_addr constant {{.*}} c"T@\22NSString\22,N,R\00"
@objc let l: String? = nil
// -- Protocol types:
diff --git a/test/IRGen/objc_simd.sil b/test/IRGen/objc_simd.sil
index d257c4f..b037f54 100644
--- a/test/IRGen/objc_simd.sil
+++ b/test/IRGen/objc_simd.sil
@@ -57,7 +57,7 @@
// armv7s-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { float, float, float, float } @simd_native_args(float, float, float, float)
// armv7k-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { float, float, float, float } @simd_native_args(float, float, float, float)
// powerpc64-LABEL: define{{( dllexport)?}}{{( protected)?}} void @simd_native_args(%T4simd6float4V* noalias nocapture sret, %T4simd6float4V* noalias nocapture dereferenceable({{.*}}))
-// powerpc64le-LABEL: define{{( dllexport)?}}{{( protected)?}} void @simd_native_args(%T4simd6float4V* noalias nocapture sret, %T4simd6float4V* noalias nocapture dereferenceable({{.*}}))
+// powerpc64le-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { float, float, float, float } @simd_native_args(float, float, float, float)
// s390x-LABEL: define{{( dllexport)?}}{{( protected)?}} void @simd_native_args(%T4simd6float4V* noalias nocapture sret, %T4simd6float4V* noalias nocapture dereferenceable({{.*}}))
sil @simd_native_args : $@convention(thin) (float4) -> float4 {
entry(%x : $float4):
diff --git a/test/IRGen/partial_apply.sil b/test/IRGen/partial_apply.sil
index 7e443c2..87974e3 100644
--- a/test/IRGen/partial_apply.sil
+++ b/test/IRGen/partial_apply.sil
@@ -10,6 +10,9 @@
sil @$s13partial_apply10SwiftClassCfD : $@convention(method) (SwiftClass) -> ()
sil @partially_applyable_to_class : $@convention(thin) (@owned SwiftClass) -> ()
+sil @partially_applyable_to_two_classes : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> ()
+
+sil @use_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { i8*, %swift.refcounted* } @partial_apply_class(%T13partial_apply10SwiftClassC*) {{.*}} {
// CHECK: entry:
@@ -24,6 +27,53 @@
return %g : $@callee_owned () -> ()
}
+// CHECK: define{{.*}} swiftcc void @partial_apply_class_on_stack(%T13partial_apply10SwiftClassC*)
+// CHECK: entry:
+// CHECK: [[CTX:%.*]] = bitcast %T13partial_apply10SwiftClassC* %0 to %swift.opaque*
+// CHECK: call swiftcc void @use_closure(i8* bitcast (void (%swift.refcounted*)* @"$s28partially_applyable_to_classTA.1" to i8*), %swift.opaque* [[CTX]])
+// CHECK: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T13partial_apply10SwiftClassC*)*)(%T13partial_apply10SwiftClassC* %0)
+// CHECK: ret void
+// CHECK: }
+
+sil @partial_apply_class_on_stack : $@convention(thin) (@owned SwiftClass) -> () {
+entry(%a : $SwiftClass):
+ %f = function_ref @partially_applyable_to_class : $@convention(thin) (@owned SwiftClass) -> ()
+ %c = partial_apply [callee_guaranteed] [on_stack] %f(%a) : $@convention(thin) (@owned SwiftClass) -> ()
+ %use = function_ref @use_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ apply %use(%c) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ dealloc_stack %c : $@noescape @callee_guaranteed () ->()
+ strong_release %a : $SwiftClass
+ %t = tuple()
+ return %t : $()
+}
+
+// CHECK: define{{.*}} swiftcc void @partial_apply_two_classes_on_stack(%T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC*)
+// CHECK: entry:
+// CHECK: [[CTX:%.*]] = alloca i8, i64 32, align 16
+// CHECK: [[CTX2:%.*]] = bitcast i8* [[CTX]] to %swift.opaque*
+// CHECK: [[LAYOUT:%.*]] = bitcast %swift.opaque* [[CTX2]] to <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>*
+// CHECK: [[CAPTURE1:%.*]] = getelementptr inbounds <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>, <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>* [[LAYOUT]], i32 0, i32 1
+// CHECK: store %T13partial_apply10SwiftClassC* %0, %T13partial_apply10SwiftClassC** [[CAPTURE1]], align 8
+// CHECK: [[CAPTURE2:%.*]] = getelementptr inbounds <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>, <{ %swift.refcounted, %T13partial_apply10SwiftClassC*, %T13partial_apply10SwiftClassC* }>* [[LAYOUT]], i32 0, i32 2
+// CHECK: store %T13partial_apply10SwiftClassC* %1, %T13partial_apply10SwiftClassC** [[CAPTURE2]], align 8
+// CHECK: call swiftcc void @use_closure(i8* bitcast (void (%swift.refcounted*)* @"$s34partially_applyable_to_two_classesTA" to i8*), %swift.opaque* [[CTX2]])
+// CHECK: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T13partial_apply10SwiftClassC*)*)(%T13partial_apply10SwiftClassC* %0)
+// CHECK: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T13partial_apply10SwiftClassC*)*)(%T13partial_apply10SwiftClassC* %1)
+// CHECK: ret void
+// CHECK: }
+
+sil @partial_apply_two_classes_on_stack : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> () {
+entry(%a : $SwiftClass, %b: $SwiftClass):
+ %f = function_ref @partially_applyable_to_two_classes : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> ()
+ %c = partial_apply [callee_guaranteed] [on_stack] %f(%a, %b) : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> ()
+ %use = function_ref @use_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ apply %use(%c) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ dealloc_stack %c : $@noescape @callee_guaranteed () ->()
+ strong_release %a : $SwiftClass
+ strong_release %b : $SwiftClass
+ %t = tuple()
+ return %t : $()
+}
//
// Check that partially applied generic parameters are correctly substituted
// in the forwarder.
@@ -552,4 +602,27 @@
return %5 : $@callee_guaranteed () -> (@owned A1, @error Error)
}
+sil @capture_class : $@convention(thin) (@guaranteed A3) -> ()
+
+// CHECK-LABEL: define{{.*}} swiftcc i8* @partial_apply_stack_in_coroutine(i8* {{.*}}, %T13partial_apply2A3C*)
+// CHECK: entry:
+// CHECK: [[CLOSURE_CONTEXT:%.*]] = bitcast %T13partial_apply2A3C* %1 to %swift.opaque*
+// CHECK: [[CONTEXT:%.*]] = bitcast %swift.opaque* [[CLOSURE_CONTEXT]] to %swift.refcounted*
+// CHECK: call swiftcc void @"$s13capture_classTA"(%swift.refcounted* swiftself [[CONTEXT]])
+sil @partial_apply_stack_in_coroutine : $@yield_once (@owned A3) -> () {
+entry(%0: $A3):
+ %f = function_ref @capture_class : $@convention(thin) (@guaranteed A3) -> ()
+ %p = partial_apply [callee_guaranteed] [on_stack] %f(%0) : $@convention(thin) (@guaranteed A3) -> ()
+ apply %p() : $@noescape @callee_guaranteed () -> ()
+ dealloc_stack %p : $@noescape @callee_guaranteed () -> ()
+ %1000 = integer_literal $Builtin.Int32, 1000
+ yield (), resume resume, unwind unwind
+
+resume:
+ %ret = tuple ()
+ return %ret : $()
+
+unwind:
+ unwind
+}
sil_vtable A3 {}
diff --git a/test/IRGen/pic.swift b/test/IRGen/pic.swift
index b458b6f..a10b06f 100644
--- a/test/IRGen/pic.swift
+++ b/test/IRGen/pic.swift
@@ -60,3 +60,7 @@
// aarch64: str [[REG2]], [sp]
// aarch64: bl swift_endAccess
// aarch64: ldr x0, [sp]
+
+// powerpc64le-LABEL: {{_?}}$s4main10use_globalSiyF:
+// powerpc64le: bl swift_beginAccess
+// powerpc64le: addi 3, 3, ($s4main6globalSivp)@toc@l
diff --git a/test/Index/Store/output-failure.swift b/test/Index/Store/output-failure.swift
index 1cfa146..285443b 100644
--- a/test/Index/Store/output-failure.swift
+++ b/test/Index/Store/output-failure.swift
@@ -1,3 +1,4 @@
+// XFAIL: CPU=powerpc64le
// RUN: %empty-directory(%t)
// RUN: mkdir %t/idx
diff --git a/test/Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift b/test/Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift
index c57ced6..2274d1c 100644
--- a/test/Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift
+++ b/test/Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift
@@ -8,7 +8,7 @@
public struct CGFloat {
#if arch(i386) || arch(arm)
public typealias UnderlyingType = Float
-#elseif arch(x86_64) || arch(arm64)
+#elseif arch(x86_64) || arch(arm64) || arch(powerpc64le)
public typealias UnderlyingType = Double
#endif
diff --git a/test/Interpreter/generic_casts.swift b/test/Interpreter/generic_casts.swift
index bf87feb..ae63157 100644
--- a/test/Interpreter/generic_casts.swift
+++ b/test/Interpreter/generic_casts.swift
@@ -3,6 +3,7 @@
// RUN: %target-codesign %t/a.out.optimized
// RUN: %target-run %t/a.out.optimized | %FileCheck %s
// REQUIRES: executable_test
+// XFAIL: CPU=powerpc64le
// FIXME: rdar://problem/19648117 Needs splitting objc parts out
diff --git a/test/Misc/stats_dir_tracer.swift b/test/Misc/stats_dir_tracer.swift
index 12795d8..90be632 100644
--- a/test/Misc/stats_dir_tracer.swift
+++ b/test/Misc/stats_dir_tracer.swift
@@ -2,9 +2,9 @@
// RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t %s -trace-stats-events
// RUN: %FileCheck -input-file %t/*.csv %s
-// CHECK: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumTypesDeserialized",[0-9]+,[0-9]+,"Call","\[.*stats_dir_tracer.swift.*\]"}}
-// CHECK: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumConstraintScopes",[0-9]+,[0-9]+,"Sequence","\[.*stats_dir_tracer.swift.*\]"}}
-// CHECK: {{[0-9]+,[0-9]+,"exit","SuperclassDeclRequest","Sema.SuperclassDeclRequest",[0-9]+,[0-9]+,"Bar","\[.*stats_dir_tracer.swift.*\]"}}
+// CHECK-DAG: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumTypesDeserialized",[0-9]+,[0-9]+,"Call","\[.*stats_dir_tracer.swift.*\]"}}
+// CHECK-DAG: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumConstraintScopes",[0-9]+,[0-9]+,"Sequence","\[.*stats_dir_tracer.swift.*\]"}}
+// CHECK-DAG: {{[0-9]+,[0-9]+,"exit","SuperclassDeclRequest","Sema.SuperclassDeclRequest",[0-9]+,[0-9]+,"Bar","\[.*stats_dir_tracer.swift.*\]"}}
public func foo() {
print("hello")
diff --git a/test/ParseableInterface/ModuleCache/force-module-loading-mode-archs.swift b/test/ParseableInterface/ModuleCache/force-module-loading-mode-archs.swift
index 195b4c1..a764baf 100644
--- a/test/ParseableInterface/ModuleCache/force-module-loading-mode-archs.swift
+++ b/test/ParseableInterface/ModuleCache/force-module-loading-mode-archs.swift
@@ -1,4 +1,5 @@
// RUN: %empty-directory(%t)
+// XFAIL: CPU=powerpc64le
// 1. Not finding things is okay.
// RUN: not env SWIFT_FORCE_MODULE_LOADING=prefer-parseable %target-swift-frontend -typecheck -parse-stdlib -module-cache-path %t/MCP %s 2>&1 | %FileCheck -check-prefix=NO-SUCH-MODULE %s
diff --git a/test/ParseableInterface/ModuleCache/force-module-loading-mode-framework.swift b/test/ParseableInterface/ModuleCache/force-module-loading-mode-framework.swift
index b1f0d5c..b2f705b 100644
--- a/test/ParseableInterface/ModuleCache/force-module-loading-mode-framework.swift
+++ b/test/ParseableInterface/ModuleCache/force-module-loading-mode-framework.swift
@@ -1,4 +1,5 @@
// RUN: %empty-directory(%t)
+// XFAIL: CPU=powerpc64le
// 1. Not finding things is okay.
// RUN: not env SWIFT_FORCE_MODULE_LOADING=prefer-parseable %target-swift-frontend -typecheck -parse-stdlib -module-cache-path %t/MCP %s 2>&1 | %FileCheck -check-prefix=NO-SUCH-MODULE %s
diff --git a/test/ParseableInterface/ModuleCache/force-module-loading-mode.swift b/test/ParseableInterface/ModuleCache/force-module-loading-mode.swift
index 2f934bc..7d611f1 100644
--- a/test/ParseableInterface/ModuleCache/force-module-loading-mode.swift
+++ b/test/ParseableInterface/ModuleCache/force-module-loading-mode.swift
@@ -1,4 +1,5 @@
// RUN: %empty-directory(%t)
+// XFAIL: CPU=powerpc64le
// 1. Not finding things is okay.
// RUN: not env SWIFT_FORCE_MODULE_LOADING=prefer-parseable %target-swift-frontend -typecheck -parse-stdlib -module-cache-path %t/MCP %s 2>&1 | %FileCheck -check-prefix=NO-SUCH-MODULE %s
diff --git a/test/Runtime/linux-fatal-backtrace.swift b/test/Runtime/linux-fatal-backtrace.swift
index 6df5ec3..40b6abe 100644
--- a/test/Runtime/linux-fatal-backtrace.swift
+++ b/test/Runtime/linux-fatal-backtrace.swift
@@ -4,6 +4,7 @@
// REQUIRES: executable_test
// REQUIRES: OS=linux-gnu
// REQUIRES: lldb
+// XFAIL: CPU=powerpc64le
// Backtraces are not emitted when optimizations are enabled. This test can not
// run when optimizations are enabled.
diff --git a/test/SIL/Serialization/opaque_values_serialize.sil b/test/SIL/Serialization/opaque_values_serialize.sil
index a634368..4399efb 100644
--- a/test/SIL/Serialization/opaque_values_serialize.sil
+++ b/test/SIL/Serialization/opaque_values_serialize.sil
@@ -1,3 +1,4 @@
+// XFAIL: CPU=powerpc64le
// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
// RUN: %empty-directory(%t)
// FIXME: <rdar://problem/29281364> sil-opt -verify is broken
diff --git a/test/SILGen/enum.swift b/test/SILGen/enum.swift
index 04b0dcf..b44e005 100644
--- a/test/SILGen/enum.swift
+++ b/test/SILGen/enum.swift
@@ -1,19 +1,12 @@
-// RUN: %target-swift-emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
-
-precedencegroup AssignmentPrecedence { assignment: true }
-
-enum Optional<Wrapped> {
- case none
- case some(Wrapped)
-}
+// RUN: %target-swift-emit-silgen -parse-as-library %s | %FileCheck %s
enum Boolish {
case falsy
case truthy
}
-// CHECK-LABEL: sil hidden [ossa] @$ss13Boolish_casesyyF
+// CHECK-LABEL: sil hidden [ossa] @$s4enum13Boolish_casesyyF
func Boolish_cases() {
// CHECK: [[BOOLISH:%[0-9]+]] = metatype $@thin Boolish.Type
// CHECK-NEXT: [[FALSY:%[0-9]+]] = enum $Boolish, #Boolish.falsy!enumelt
@@ -24,18 +17,16 @@
_ = Boolish.truthy
}
-struct Int {}
-
enum Optionable {
case nought
case mere(Int)
}
-// CHECK-LABEL: sil hidden [ossa] @$ss16Optionable_casesyySiF
+// CHECK-LABEL: sil hidden [ossa] @$s4enum16Optionable_casesyySiF
func Optionable_cases(_ x: Int) {
// CHECK: [[METATYPE:%.*]] = metatype $@thin Optionable.Type
- // CHECK: [[FN:%.*]] = function_ref @$ss10OptionableO4mereyABSicABmF
+ // CHECK: [[FN:%.*]] = function_ref @$s4enum10OptionableO4mereyACSicACmFTc
// CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
// CHECK-NEXT: destroy_value [[CTOR]]
_ = Optionable.mere
@@ -45,13 +36,13 @@
_ = Optionable.mere(x)
}
-// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$ss10OptionableO4mereyABSicABmF
-// CHECK: [[FN:%.*]] = function_ref @$ss10OptionableO4mereyABSicABmF
+// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$s4enum10OptionableO4mereyACSicACmF
+// CHECK: [[FN:%.*]] = function_ref @$s4enum10OptionableO4mereyACSicACmF
// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
// CHECK-NEXT: return [[METHOD]]
// CHECK-NEXT: }
-// CHECK-LABEL: sil shared [transparent] [ossa] @$ss10OptionableO4mereyABSicABmF
+// CHECK-LABEL: sil shared [transparent] [ossa] @$s4enum10OptionableO4mereyACSicACmF
// CHECK: [[RES:%.*]] = enum $Optionable, #Optionable.mere!enumelt.1, %0 : $Int
// CHECK-NEXT: return [[RES]] : $Optionable
// CHECK-NEXT: }
@@ -65,11 +56,11 @@
case phantom(S)
}
-// CHECK-LABEL: sil hidden [ossa] @$ss17AddressOnly_casesyys1SVF
+// CHECK-LABEL: sil hidden [ossa] @$s4enum17AddressOnly_casesyyAA1SVF
func AddressOnly_cases(_ s: S) {
// CHECK: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
- // CHECK: [[FN:%.*]] = function_ref @$ss11AddressOnlyO4mereyABs1P_pcABmF
+ // CHECK: [[FN:%.*]] = function_ref @$s4enum11AddressOnlyO4mereyAcA1P_pcACmFTc
// CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
// CHECK-NEXT: destroy_value [[CTOR]]
_ = AddressOnly.mere
@@ -105,29 +96,29 @@
// CHECK: return
}
-// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$ss11AddressOnlyO4mereyABs1P_pcABmF
-// CHECK: [[FN:%.*]] = function_ref @$ss11AddressOnlyO4mereyABs1P_pcABmF
+// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$s4enum11AddressOnlyO4mereyAcA1P_pcACmFTc
+// CHECK: [[FN:%.*]] = function_ref @$s4enum11AddressOnlyO4mereyAcA1P_pcACmF
// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
// CHECK-NEXT: // function_ref
-// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$ss1P_ps11AddressOnlyOIegir_sAA_pACIegnr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in P) -> @out AddressOnly) -> @out AddressOnly
+// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$s4enum1P_pAA11AddressOnlyOIegir_AaB_pADIegnr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in P) -> @out AddressOnly) -> @out AddressOnly
// CHECK-NEXT: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[METHOD]])
// CHECK-NEXT: return [[CANONICAL_THUNK]] : $@callee_guaranteed (@in_guaranteed P) -> @out AddressOnly
// CHECK-NEXT: }
-// CHECK-LABEL: sil shared [transparent] [ossa] @$ss11AddressOnlyO4mereyABs1P_pcABmF : $@convention
+// CHECK-LABEL: sil shared [transparent] [ossa] @$s4enum11AddressOnlyO4mereyAcA1P_pcACmF : $@convention
// CHECK: bb0([[ARG0:%.*]] : $*AddressOnly, [[ARG1:%.*]] : $*P, [[ARG2:%.*]] : $@thin AddressOnly.Type):
// CHECK: [[RET_DATA:%.*]] = init_enum_data_addr [[ARG0]] : $*AddressOnly, #AddressOnly.mere!enumelt.1
// CHECK-NEXT: copy_addr [take] [[ARG1]] to [initialization] [[RET_DATA]] : $*P
// CHECK-NEXT: inject_enum_addr [[ARG0]] : $*AddressOnly, #AddressOnly.mere!enumelt.1
// CHECK: return
-// CHECK-NEXT: } // end sil function '$ss11AddressOnlyO4mereyABs1P_pcABmF'
+// CHECK-NEXT: } // end sil function '$s4enum11AddressOnlyO4mereyAcA1P_pcACmF'
enum PolyOptionable<T> {
case nought
case mere(T)
}
-// CHECK-LABEL: sil hidden [ossa] @$ss20PolyOptionable_casesyyxlF
+// CHECK-LABEL: sil hidden [ossa] @$s4enum20PolyOptionable_casesyyxlF
func PolyOptionable_cases<T>(_ t: T) {
// CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<T>.Type
@@ -154,7 +145,7 @@
// The substituted type is loadable and trivial here
-// CHECK-LABEL: sil hidden [ossa] @$ss32PolyOptionable_specialized_casesyySiF
+// CHECK-LABEL: sil hidden [ossa] @$s4enum32PolyOptionable_specialized_casesyySiF
func PolyOptionable_specialized_cases(_ t: Int) {
// CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<Int>.Type
@@ -172,23 +163,23 @@
// Regression test for a bug where temporary allocations created as a result of
// tuple implosion were not deallocated in enum constructors.
-struct String { var ptr: Builtin.NativeObject }
+struct String { var ptr: AnyObject }
enum Foo { case a(P, String) }
// Curry Thunk for Foo.a(_:)
//
-// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$ss3FooO1ayABs1P_p_SStcABmF
-// CHECK: [[FN:%.*]] = function_ref @$ss3FooO1ayABs1P_p_SStcABmF
+// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmFTc
+// CHECK: [[FN:%.*]] = function_ref @$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmF
// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
// CHECK-NEXT: // function_ref
-// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$ss1P_pSSs3FooOIegixr_sAA_pSSACIegngr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed String, @guaranteed @callee_guaranteed (@in P, @owned String) -> @out Foo) -> @out Foo
+// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$s4enum1P_pAA6StringVAA3FooOIegixr_AaB_pAdFIegngr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed String, @guaranteed @callee_guaranteed (@in P, @owned String) -> @out Foo) -> @out Foo
// CHECK-NEXT: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[METHOD]])
// CHECK-NEXT: return [[CANONICAL_THUNK]]
// CHECK-NEXT: }
// Foo.a(_:)
-// CHECK-LABEL: sil shared [transparent] [ossa] @$ss3FooO1ayABs1P_p_SStcABmF
+// CHECK-LABEL: sil shared [transparent] [ossa] @$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmF
// CHECK: bb0([[ARG0:%.*]] : $*Foo, [[ARG1:%.*]] : $*P, [[ARG2:%.*]] : @owned $String, [[ARG3:%.*]] : $@thin Foo.Type):
// CHECK: [[PAYLOAD:%.*]] = init_enum_data_addr [[ARG0]] : $*Foo, #Foo.a!enumelt.1
// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PAYLOAD]] : $*(P, String), 0
@@ -197,7 +188,7 @@
// CHECK-NEXT: store [[ARG2]] to [init] [[RIGHT]]
// CHECK-NEXT: inject_enum_addr [[ARG0]] : $*Foo, #Foo.a!enumelt.1
// CHECK: return
-// CHECK-NEXT: } // end sil function '$ss3FooO1ayABs1P_p_SStcABmF'
+// CHECK-NEXT: } // end sil function '$s4enum3FooO1ayAcA1P_p_AA6StringVtcACmF'
func Foo_cases() {
_ = Foo.a
@@ -213,3 +204,33 @@
func makeIndirectEnum<T>(_ payload: T) -> Indirect<T> {
return Indirect.payload((payload, other: payload))
}
+
+// https://bugs.swift.org/browse/SR-9675
+
+enum TrailingClosureConcrete {
+ case label(fn: () -> Int)
+ case noLabel(() -> Int)
+ case twoElementsLabel(x: Int, fn: () -> Int)
+ case twoElementsNoLabel(_ x: Int, _ fn: () -> Int)
+}
+
+func useTrailingClosureConcrete() {
+ _ = TrailingClosureConcrete.label { 0 }
+ _ = TrailingClosureConcrete.noLabel { 0 }
+ _ = TrailingClosureConcrete.twoElementsLabel(x: 0) { 0 }
+ _ = TrailingClosureConcrete.twoElementsNoLabel(0) { 0 }
+}
+
+enum TrailingClosureGeneric<T> {
+ case label(fn: () -> T)
+ case noLabel(() -> T)
+ case twoElementsLabel(x: T, fn: () -> T)
+ case twoElementsNoLabel(_ x: T, _ fn: () -> T)
+}
+
+func useTrailingClosureGeneric<T>(t: T) {
+ _ = TrailingClosureGeneric<T>.label { t }
+ _ = TrailingClosureGeneric<T>.noLabel { t }
+ _ = TrailingClosureGeneric<T>.twoElementsLabel(x: t) { t }
+ _ = TrailingClosureGeneric<T>.twoElementsNoLabel(t) { t }
+}
\ No newline at end of file
diff --git a/test/SILGen/guaranteed_normal_args_curry_thunks.swift b/test/SILGen/guaranteed_normal_args_curry_thunks.swift
index 508fcd0..90942f5 100644
--- a/test/SILGen/guaranteed_normal_args_curry_thunks.swift
+++ b/test/SILGen/guaranteed_normal_args_curry_thunks.swift
@@ -119,9 +119,9 @@
// CHECK: return [[THUNK_PA]]
// CHECK: } // end sil function '$ss017LoadableClassInitA0CyABs5KlassCcfCTcTd'
-// Canonical Thunk.
+// Reabstraction thunk.
//
-// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$ss5KlassCs017LoadableClassInitB0CIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableClassInitLoadable) -> @owned LoadableClassInitLoadable {
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs017LoadableClassInitB0CIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableClassInitLoadable) -> @owned LoadableClassInitLoadable {
// CHECK: bb0([[CLASS:%.*]] : @guaranteed $Klass, [[PA:%.*]] : @guaranteed $@callee_guaranteed (@owned Klass) -> @owned LoadableClassInitLoadable):
// CHECK: [[CLASS_COPY:%.*]] = copy_value [[CLASS]]
// CHECK: [[RESULT:%.*]] = apply [[PA]]([[CLASS_COPY]])
@@ -153,9 +153,9 @@
// CHECK: return [[THUNK_PA]]
// CHECK: } // end sil function '$ss018LoadableStructInitA0VyABs5KlassCcfCTc'
-// Canonical Thunk.
+// Reabstraction thunk.
//
-// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$ss5KlassCs018LoadableStructInitB0VIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableStructInitLoadable) -> @owned LoadableStructInitLoadable {
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs018LoadableStructInitB0VIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableStructInitLoadable) -> @owned LoadableStructInitLoadable {
// CHECK: bb0([[CLASS:%.*]] : @guaranteed $Klass, [[PA:%.*]] : @guaranteed $@callee_guaranteed (@owned Klass) -> @owned LoadableStructInitLoadable):
// CHECK: [[CLASS_COPY:%.*]] = copy_value [[CLASS]]
// CHECK: [[RESULT:%.*]] = apply [[PA]]([[CLASS_COPY]])
@@ -191,14 +191,14 @@
// CHECK: return [[THUNK]]
// CHECK: } // end sil function '$ss25AddrOnlyStructInitGenericVyAByxGxcfCTc'
-// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$sxs25AddrOnlyStructInitGenericVyxGIegir_xACIegnr_lTR : $@convention(thin) <T> (@in_guaranteed T, @guaranteed @callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>) -> @out AddrOnlyStructInitGeneric<T> {
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$sxs25AddrOnlyStructInitGenericVyxGIegir_xACIegnr_lTR : $@convention(thin) <T> (@in_guaranteed T, @guaranteed @callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>) -> @out AddrOnlyStructInitGeneric<T> {
// CHECK: bb0([[ARG0:%.*]] : $*AddrOnlyStructInitGeneric<T>, [[ARG1:%.*]] : $*T, [[ARG2:%.*]] : @guaranteed $@callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>):
// CHECK: [[STACK:%.*]] = alloc_stack $T
// CHECK: copy_addr [[ARG1]] to [initialization] [[STACK]] : $*T
// CHECK: apply [[ARG2]]([[ARG0]], [[STACK]]) : $@callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>
// CHECK: } // end sil function '$sxs25AddrOnlyStructInitGenericVyxGIegir_xACIegnr_lTR'
-// CHECK_LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs25AddrOnlyStructInitGenericVyABGIegnr_AbEIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@in_guaranteed Klass) -> @out AddrOnlyStructInitGeneric<Klass>) -> @owned AddrOnlyStructInitGeneric<Klass> {
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs25AddrOnlyStructInitGenericVyABGIegnr_AbEIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@in_guaranteed Klass) -> @out AddrOnlyStructInitGeneric<Klass>) -> @owned AddrOnlyStructInitGeneric<Klass> {
// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Klass, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed Klass) -> @out AddrOnlyStructInitGeneric<Klass>):
// CHECK: [[STACK:%.*]] = alloc_stack $Klass
// CHECK: [[ARG0_COPY:%.*]] = copy_value [[ARG0]]
@@ -253,9 +253,9 @@
// CHECK: return [[CANONICAL_THUNK]]
// CHECK: } // end sil function '$ss20ProtocolInitLoadableP1txs5KlassC_tcfCTc'
-// Canonical thunk
+// Reabstraction thunk.
//
-// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$ss5KlassCxIegxr_ABxIeggr_s20ProtocolInitLoadableRzlTR : $@convention(thin) <Self where Self : ProtocolInitLoadable> (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @out Self) -> @out Self {
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCxIegxr_ABxIeggr_s20ProtocolInitLoadableRzlTR : $@convention(thin) <Self where Self : ProtocolInitLoadable> (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @out Self) -> @out Self {
// CHECK: bb0([[ARG0:%.*]] : $*Self, [[ARG1:%.*]] : @guaranteed $Klass, [[ARG2:%.*]] : @guaranteed $@callee_guaranteed (@owned Klass) -> @out Self):
// CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]]
// CHECK: apply [[ARG2]]([[ARG0]], [[ARG1_COPY]])
diff --git a/test/SILGen/partial_apply_override.swift b/test/SILGen/partial_apply_override.swift
new file mode 100644
index 0000000..07fdeaf
--- /dev/null
+++ b/test/SILGen/partial_apply_override.swift
@@ -0,0 +1,39 @@
+// RUN: %target-swift-emit-silgen %s | %FileCheck %s
+
+// rdar://45671537
+
+class Converter<Input, Output> {
+ func convert(input: Input) -> Output {
+ fatalError("Has to be overriden")
+ }
+}
+
+class StringIntConverter: Converter<String, Int> {
+ override func convert(input: String) -> Int {
+ return 0
+ }
+}
+
+public func convert(strings: [String]) -> [Int] {
+ return strings.map(StringIntConverter().convert)
+}
+
+// CHECK-LABEL: sil [ossa] @$s22partial_apply_override7convert7stringsSaySiGSaySSG_tF :
+// CHECK: [[CONVERTER_TYPE:%.*]] = metatype $@thick StringIntConverter.Type
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[ALLOC_CONVERTER:%.*]] = function_ref @$s22partial_apply_override18StringIntConverterCACycfC :
+// CHECK-NEXT: [[CONVERTER:%.*]] = apply [[ALLOC_CONVERTER]]([[CONVERTER_TYPE]])
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[CURRY_THUNK:%.*]] = function_ref @$s22partial_apply_override18StringIntConverterC7convert5inputSiSS_tFTc : $@convention(thin) (@guaranteed StringIntConverter) -> @owned @callee_guaranteed (@guaranteed String) -> Int
+// CHECK-NEXT: [[CURRY_RESULT:%.*]] = apply [[CURRY_THUNK]]([[CONVERTER]])
+// CHECK-NEXT: destroy_value [[CONVERTER]] :
+
+// CHECK-LABEL: sil shared [thunk] [ossa] @$s22partial_apply_override18StringIntConverterC7convert5inputSiSS_tFTc :
+// CHECK-SAME: $@convention(thin) (@guaranteed StringIntConverter) -> @owned @callee_guaranteed (@guaranteed String) -> Int
+// CHECK: [[METHOD:%.*]] = class_method %0 : $StringIntConverter, #StringIntConverter.convert!1 : (StringIntConverter) -> (String) -> Int, $@convention(method) (@in_guaranteed String, @guaranteed StringIntConverter) -> @out Int
+// CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value %0 :
+// CHECK-NEXT: [[BOUND_METHOD:%.*]] = partial_apply [callee_guaranteed] [[METHOD]]([[SELF_COPY]])
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[THUNK:%.*]] = function_ref @$sSSSiIegnr_SSSiIeggd_TR : $@convention(thin) (@guaranteed String, @guaranteed @callee_guaranteed (@in_guaranteed String) -> @out Int) -> Int
+// CHECK-NEXT: [[REABSTRACTED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[BOUND_METHOD]])
+// CHECK-NEXT: return [[REABSTRACTED]]
diff --git a/test/SILGen/reabstract.swift b/test/SILGen/reabstract.swift
index d1e09d3..9ca56aa 100644
--- a/test/SILGen/reabstract.swift
+++ b/test/SILGen/reabstract.swift
@@ -37,13 +37,12 @@
// MANDATORY-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T2]]
// MANDATORY-NEXT: //{{.*}}reabstraction thunk
// MANDATORY-NEXT: [[T3:%.*]] = function_ref [[THUNK:@.*]] :
-// MANDATORY-NEXT: [[T4:%.*]] = partial_apply [callee_guaranteed] [[T3]]([[CVT]])
-// MANDATORY-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T4]]
+// MANDATORY-NEXT: [[T4:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[T3]]([[CVT]])
// MANDATORY-NEXT: strong_release [[T2]]
// MANDATORY-NEXT: // function_ref
// MANDATORY-NEXT: [[T0:%.*]] = function_ref @$s10reabstract6takeFn{{[_0-9a-zA-Z]*}}F
-// MANDATORY-NEXT: apply [[T0]]<Int>([[CVT]])
-// MANDATORY-NEXT: strong_release [[T4]]
+// MANDATORY-NEXT: apply [[T0]]<Int>([[T4]])
+// MANDATORY-NEXT: dealloc_stack [[T4]] : $@noescape @callee_guaranteed (@in_guaranteed Int) -> @out Optional<Int>
// MANDATORY-NEXT: strong_release [[T2]]
// MANDATORY-NEXT: tuple ()
// MANDATORY-NEXT: return
diff --git a/test/SILOptimizer/access_enforcement_noescape.swift b/test/SILOptimizer/access_enforcement_noescape.swift
index 212be46..002c675 100644
--- a/test/SILOptimizer/access_enforcement_noescape.swift
+++ b/test/SILOptimizer/access_enforcement_noescape.swift
@@ -85,12 +85,10 @@
doTwo({ _ = x }, { _ = x })
}
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape09inoutReadE01xySiz_tF : $@convention(thin) (@inout Int) -> () {
-// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed] [on_stack]
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK: apply %{{.*}}([[PA1]], [[PA2]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape09inoutReadE01xySiz_tF'
// closure #1 in inoutReadRead(x:)
@@ -119,10 +117,9 @@
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape11readBoxReadyyF : $@convention(thin) () -> () {
// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK: apply %{{.*}}([[CVT1]], [[PA2]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape11readBoxReadyyF'
// closure #1 in readBoxRead()
@@ -153,12 +150,10 @@
doTwo({ _ = x }, { x = 42 })
}
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape9readWriteyyF : $@convention(thin) () -> () {
-// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed] [on_stack]
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK: apply %{{.*}}([[PA1]], [[PA2]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape9readWriteyyF'
// closure #1 in readWrite()
@@ -195,10 +190,9 @@
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape12readBoxWriteyyF : $@convention(thin) () -> () {
// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK: apply %{{.*}}([[CVT1]], [[PA2]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape12readBoxWriteyyF'
// closure #1 in readBoxWrite()
@@ -230,11 +224,10 @@
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape12readWriteBoxyyF : $@convention(thin) () -> () {
// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT2]], [[CVT1]])
+// CHECK: apply %{{.*}}([[PA2]], [[CVT1]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape12readWriteBoxyyF'
// closure #1 in readWriteBox()
@@ -319,12 +312,10 @@
}
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape10writeWriteyyF : $@convention(thin) () -> () {
-// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed] [on_stack]
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK: apply %{{.*}}([[PA1]], [[PA2]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape10writeWriteyyF'
// closure #1 in writeWrite()
@@ -348,12 +339,10 @@
}
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape010inoutWriteE01xySiz_tF : $@convention(thin) (@inout Int) -> () {
-// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed] [on_stack]
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK: apply %{{.*}}([[PA1]], [[PA2]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape010inoutWriteE01xySiz_tF'
// closure #1 in inoutWriteWrite(x:)
@@ -381,11 +370,10 @@
// CHECK-LABEL: sil hidden @$s27access_enforcement_noescape13writeWriteBoxyyF : $@convention(thin) () -> () {
// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
-// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack]
// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
// CHECK-NOT: begin_access
-// CHECK: apply %{{.*}}([[CVT2]], [[CVT1]])
+// CHECK: apply %{{.*}}([[PA2]], [[CVT1]])
// CHECK-LABEL: } // end sil function '$s27access_enforcement_noescape13writeWriteBoxyyF'
// closure #1 in writeWriteBox()
diff --git a/test/SILOptimizer/capture_promotion.sil b/test/SILOptimizer/capture_promotion.sil
index 8dd3d86..839d794 100644
--- a/test/SILOptimizer/capture_promotion.sil
+++ b/test/SILOptimizer/capture_promotion.sil
@@ -407,3 +407,70 @@
return %21 : $@callee_guaranteed () -> Int
}
+
+// CHECK-LABEL: sil @test_capture_promotion_on_stack
+sil @test_capture_promotion_on_stack : $@convention(thin) () -> () {
+bb0:
+ %0 = tuple ()
+ %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Foo>
+ %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Foo>, 0
+ %2 = function_ref @foo_allocating_init : $@convention(thin) (@thick Foo.Type) -> @owned Foo
+ %3 = metatype $@thick Foo.Type
+ %4 = apply %2(%3) : $@convention(thin) (@thick Foo.Type) -> @owned Foo
+ store %4 to %1a : $*Foo
+ %6 = alloc_box $<τ_0_0> { var τ_0_0 } <Baz>
+ %6a = project_box %6 : $<τ_0_0> { var τ_0_0 } <Baz>, 0
+ %7 = function_ref @baz_init : $@convention(thin) (@thin Baz.Type) -> @owned Baz
+ %8 = metatype $@thin Baz.Type
+ %9 = apply %7(%8) : $@convention(thin) (@thin Baz.Type) -> @owned Baz
+ store %9 to %6a : $*Baz
+ %11 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ %11a = project_box %11 : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ %12 = function_ref @convert_from_integer_literal : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
+ %13 = metatype $@thin Int.Type
+ %14 = integer_literal $Builtin.Word, 3
+ %15 = apply %12(%14, %13) : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
+ store %15 to %11a : $*Int
+
+// CHECK-NOT: function_ref @closure0_guaranteed
+// CHECK: [[CLOSURE_PROMOTE:%.*]] = function_ref @$s19closure0_guaranteedTf2iii_n
+// CHECK-NOT: function_ref @closure0_guaranteed
+
+// The Foo variable is loaded from and retained, because it is a reference type
+// CHECK-NEXT: [[LOADFOO:%.*]] = load {{.*}} : $*Foo
+// CHECK-NEXT: strong_retain [[LOADFOO]] : $Foo
+
+// The Baz variable is loaded and retain_value'd, because it is a non-trivial
+// aggregate type
+// CHECK-NEXT: [[LOADBAZ:%.*]] = load {{.*}} : $*Baz
+// CHECK-NEXT: retain_value [[LOADBAZ:%.*]] : $Baz
+
+// The Int variable is loaded only, because it is trivial
+// CHECK-NEXT: [[LOADINT:%.*]] = load {{.*}} : $*Int
+
+// The partial apply has one value argument for each pair of arguments that was
+// previously used to capture and pass the variable by reference
+// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[CLOSURE_PROMOTE]]([[LOADFOO]], [[LOADBAZ]], [[LOADINT]])
+// CHECK-NEXT: [[MD1:%.*]] = mark_dependence [[PA]] : $@noescape @callee_guaranteed () -> Int on [[LOADFOO]] : $Foo
+// CHECK-NEXT: [[MD2:%.*]] = mark_dependence [[MD1]] : $@noescape @callee_guaranteed () -> Int on [[LOADBAZ]] : $Baz
+// CHECK-NEXT: apply [[MD2]]() : $@noescape @callee_guaranteed () -> Int
+// CHECK-NEXT: dealloc_stack [[PA]] : $@noescape @callee_guaranteed () -> Int
+// CHECK-NEXT: strong_release [[LOADFOO]] : $Foo
+// CHECK-NEXT: release_value [[LOADBAZ]] : $Baz
+// CHECK-NEXT: strong_release {{.*}} : $<τ_0_0> { var τ_0_0 } <Int>
+// CHECK-NEXT: strong_release {{.*}} : $<τ_0_0> { var τ_0_0 } <Baz>
+// CHECK-NEXT: strong_release {{.*}} : $<τ_0_0> { var τ_0_0 } <Foo>
+
+ %17 = function_ref @closure0_guaranteed : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <Foo>, @guaranteed <τ_0_0> { var τ_0_0 } <Baz>, @guaranteed <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ %21 = partial_apply [callee_guaranteed] [on_stack] %17(%1, %6, %11) : $@convention(thin) (@guaranteed <τ_0_0> { var τ_0_0 } <Foo>, @guaranteed <τ_0_0> { var τ_0_0 } <Baz>, @guaranteed <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ %md = mark_dependence %21 :$@noescape @callee_guaranteed () -> Int on %1 : $<τ_0_0> { var τ_0_0 } <Foo>
+ %md2 = mark_dependence %md :$@noescape @callee_guaranteed () -> Int on %6 : $<τ_0_0> { var τ_0_0 } <Baz>
+ %md3 = mark_dependence %md2 :$@noescape @callee_guaranteed () -> Int on %11 : $<τ_0_0> { var τ_0_0 } <Int>
+ apply %md3() : $@noescape @callee_guaranteed () -> Int
+ dealloc_stack %21 : $@noescape @callee_guaranteed () -> Int
+ strong_release %11 : $<τ_0_0> { var τ_0_0 } <Int>
+ strong_release %6 : $<τ_0_0> { var τ_0_0 } <Baz>
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <Foo>
+ %tuple = tuple()
+ return %tuple : $()
+}
diff --git a/test/SILOptimizer/capture_propagation.sil b/test/SILOptimizer/capture_propagation.sil
index 311c078..422a144 100644
--- a/test/SILOptimizer/capture_propagation.sil
+++ b/test/SILOptimizer/capture_propagation.sil
@@ -470,3 +470,40 @@
%2 = partial_apply %1(%0) : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
return %2 : $@callee_owned (Int32, Int32) -> Bool
}
+
+sil shared @test_capture_propagation2_callee_on_stack : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () {
+bb0(%0 : $@noescape @callee_guaranteed () -> ()):
+ apply %0() : $@noescape @callee_guaranteed () -> ()
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+sil shared @test_capture_propagation2_thunk_on_stack : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word, @noescape @callee_guaranteed (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()) -> () {
+bb0(%0 : $Builtin.Int32, %1 : $Builtin.FPIEEE32, %2 : $Builtin.RawPointer, %3 : $*Builtin.Word, %4 : $@noescape @callee_guaranteed (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()):
+ apply %4(%0, %1, %2, %3) : $@noescape @callee_guaranteed (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK: sil @test_capture_propagation2_caller_on_stack
+// CHECK: [[F:%.*]] = function_ref @test_capture_propagation2_callee_on_stack : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+// CHECK: [[F2:%.*]] = function_ref @$s40test_capture_propagation2_thunk_on_stack4_12353globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token808_TFtest_b1_C8_closureTf3pi0pd0psbpgpf_n : $@convention(thin) @noescape () -> ()
+// CHECK: [[CL:%.*]] = thin_to_thick_function [[F2]] : $@convention(thin) @noescape () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: apply [[F]]([[CL]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+// CHECK: return
+
+sil @test_capture_propagation2_caller_on_stack : $@convention(thin) () -> () {
+ %0 = integer_literal $Builtin.Int32, 0
+ %1 = float_literal $Builtin.FPIEEE32, 0
+ %2 = string_literal utf8 "123"
+ %3 = global_addr @globalinit_33_06E7F1D906492AE070936A9B58CBAE1C_token8 : $*Builtin.Word
+ %4 = function_ref @_TFtest_capture_propagation2_closure : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()
+ %5 = thin_to_thick_function %4 : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> () to $@noescape @callee_guaranteed (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()
+ %6 = function_ref @test_capture_propagation2_callee_on_stack : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ %7 = function_ref @test_capture_propagation2_thunk_on_stack : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word, @noescape @callee_guaranteed (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()) -> ()
+ %8 = partial_apply [callee_guaranteed] [on_stack] %7(%0, %1, %2, %3, %5) : $@convention(thin) (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word, @noescape @callee_guaranteed (Builtin.Int32, Builtin.FPIEEE32, Builtin.RawPointer, @in Builtin.Word) -> ()) -> ()
+ apply %6(%8) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ dealloc_stack %8 : $@noescape @callee_guaranteed () -> ()
+ %9999 = tuple()
+ return %9999 : $()
+}
diff --git a/test/SILOptimizer/closure_lifetime_fixup.swift b/test/SILOptimizer/closure_lifetime_fixup.swift
index 02b0706..760bb2a 100644
--- a/test/SILOptimizer/closure_lifetime_fixup.swift
+++ b/test/SILOptimizer/closure_lifetime_fixup.swift
@@ -1,4 +1,10 @@
-// RUN: %target-swift-frontend %s -sil-verify-all -enable-sil-ownership -emit-sil -o - | %FileCheck %s
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend %S/../Inputs/resilient_struct.swift -enable-resilience -emit-module -emit-module-path %t/resilient_struct.swiftmodule
+// RUN: %target-swift-frontend %S/../Inputs/resilient_enum.swift -I %t -enable-resilience -emit-module -emit-module-path %t/resilient_enum.swiftmodule
+// RUN: %target-swift-frontend %s -sil-verify-all -enable-sil-ownership -emit-sil -I %t -o - | %FileCheck %s --check-prefix=CHECK --check-prefix=%target-os
+
+import resilient_struct
+import resilient_enum
func use_closure(_ c : () -> () ) {
c()
@@ -17,14 +23,13 @@
// CHECK: bb0([[ARG:%.*]] : $C):
// CHECK: [[F:%.*]] = function_ref @$s22closure_lifetime_fixup10testSimple1cyAA1CC_tFyyXEfU_
// CHECK-NEXT: strong_retain [[ARG]] : $C
-// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F]]([[ARG]]) : $@convention(thin) (@guaranteed C) -> ()
-// CHECK-NEXT: strong_retain [[PA]] : $@callee_guaranteed () -> ()
-// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[F]]([[ARG]]) : $@convention(thin) (@guaranteed C) -> ()
+// CHECK-NEXT: [[CL:%.*]] = mark_dependence [[PA]] : $@noescape @callee_guaranteed () -> () on [[ARG]] : $C
// CHECK-NEXT: // function_ref use_closure(_:)
// CHECK-NEXT: [[F2:%.*]] = function_ref @$s22closure_lifetime_fixup04use_A0yyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
-// CHECK-NEXT: apply [[F2]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
-// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> ()
-// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> ()
+// CHECK-NEXT: apply [[F2]]([[CL]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+// CHECK-NEXT: dealloc_stack [[PA]] : $@noescape @callee_guaranteed () -> ()
+// CHECK-NEXT: strong_release [[ARG]] : $C
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return {{.*}} : $()
public func testSimple(c: C) {
@@ -35,19 +40,17 @@
// CHECK:bb0([[ARG:%.*]] : $C):
// CHECK: [[F:%.*]] = function_ref @$s22closure_lifetime_fixup11testGeneric1cyAA1CC_tFSiyXEfU_ : $@convention(thin) (@guaranteed C) -> Int
// CHECK-NEXT: strong_retain [[ARG]] : $C
-// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F]]([[ARG]]) : $@convention(thin) (@guaranteed C) -> Int
-// CHECK-NEXT: strong_retain [[PA]] : $@callee_guaranteed () -> Int
-// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
+// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[F]]([[ARG]]) : $@convention(thin) (@guaranteed C) -> Int
+// CHECK-NEXT: [[MD:%.*]] = mark_dependence [[PA]] : $@noescape @callee_guaranteed () -> Int on [[ARG]] : $C
// CHECK-NEXT: // function_ref thunk for @callee_guaranteed () -> (@unowned Int)
// CHECK-NEXT: [[F:%.*]] = function_ref @$sSiIgd_SiIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
-// CHECK-NEXT: [[PA2:%.*]] = partial_apply [callee_guaranteed] [[F]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
-// CHECK-NEXT: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> @out Int to $@noescape @callee_guaranteed () -> @out Int
-// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> Int
+// CHECK-NEXT: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[F]]([[MD]]) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
// CHECK-NEXT: // function_ref use_closureGeneric<A>(_:)
// CHECK-NEXT: [[F2:%.*]] = function_ref @$s22closure_lifetime_fixup04use_A7GenericyyxyXElF : $@convention(thin) <τ_0_0> (@noescape @callee_guaranteed () -> @out τ_0_0) -> ()
-// CHECK-NEXT: %12 = apply [[F2]]<Int>([[CVT2]]) : $@convention(thin) <τ_0_0> (@noescape @callee_guaranteed () -> @out τ_0_0) -> ()
-// CHECK-NEXT: strong_release [[PA2]] : $@callee_guaranteed () -> @out Int
-// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> Int
+// CHECK-NEXT: apply [[F2]]<Int>([[PA2]]) : $@convention(thin) <τ_0_0> (@noescape @callee_guaranteed () -> @out τ_0_0) -> ()
+// CHECK-NEXT: dealloc_stack [[PA2]]
+// CHECK-NEXT: dealloc_stack [[PA]]
+// CHECK-NEXT: strong_release [[ARG]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return {{.*}} : $()
@@ -90,3 +93,360 @@
}
return result
}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup28to_stack_of_convert_function1pySvSg_tF
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [on_stack]
+// CHECK: [[MD:%.*]] = mark_dependence [[PA]]
+// CHECK: [[CVT:%.*]] = convert_function [[MD]]
+// CHECK: [[REABSTRACT:%.*]] = function_ref @$sSvSSs5Error_pIgyozo_SvSSsAA_pIegnrzo_TR
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [on_stack] [[REABSTRACT]]([[CVT]])
+// CHECK: [[MAP:%.*]] = function_ref @$sSq3mapyqd__Sgqd__xKXEKlF
+// CHECK: try_apply [[MAP]]<UnsafeMutableRawPointer, String>({{.*}}, [[PA2]], {{.*}})
+public func to_stack_of_convert_function(p: UnsafeMutableRawPointer?) {
+ _ = p.map(String.init(describing:))
+}
+
+
+public func no_dealloc_stack_before_unreachable(_ message: String, fileName: StaticString = #file, lineNumber: Int = #line) -> Never {
+ Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
+}
+
+// Make sure closures are allocated on the stack.
+func useClosure(_ c: () -> ()) {
+}
+func useClosureThrowing(_ c: () throws -> ()) throws {
+}
+func useGenericClosure<T, V>(_ c : (T) -> V) {
+}
+func useGenericClosureThrowing<T, V>(_ c: (T) throws -> V) throws {
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup12captureClass1c1dyAA1CC_AFtKF
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup10useClosureyyyyXEF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup18useClosureThrowingyyyyKXEKF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$sIg_ytytIegnr_TR
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup17useGenericClosureyyq_xXEr0_lF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$ss5Error_pIgzo_ytytsAA_pIegnrzo_TR
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup25useGenericClosureThrowingyyq_xKXEKr0_l
+public func captureClass(c: C, d: C) throws {
+ useClosure {
+ c.doIt()
+ d.doIt()
+ }
+
+ try useClosureThrowing {
+ c.doIt()
+ d.doIt()
+ }
+
+ useGenericClosure {
+ c.doIt()
+ d.doIt()
+ }
+
+ try useGenericClosureThrowing {
+ c.doIt()
+ d.doIt()
+ }
+}
+
+public protocol DoIt {
+ func doIt()
+}
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup14captureGeneric1c1dyx_q_tKAA4DoItRzAaER_r0_lF
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup10useClosureyyyyXEF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup18useClosureThrowingyyyyKXEKF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$sIg_ytytIegnr_TR
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup17useGenericClosureyyq_xXEr0_lF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$ss5Error_pIgzo_ytytsAA_pIegnrzo_TR
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup25useGenericClosureThrowingyyq_xKXEKr0_lF
+public func captureGeneric<C :DoIt,D: DoIt>(c: C, d: D) throws {
+ useClosure {
+ c.doIt()
+ d.doIt()
+ }
+
+ try useClosureThrowing {
+ c.doIt()
+ d.doIt()
+ }
+
+ useGenericClosure {
+ c.doIt()
+ d.doIt()
+ }
+
+ try useGenericClosureThrowing {
+ c.doIt()
+ d.doIt()
+ }
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup14captureClosure1c1d1tyq_xXE_q_xXExtKr0_lF
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup10useClosureyyyyXEF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup18useClosureThrowingyyyyKXEKF
+
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$sIg_ytytIegnr_TR
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup17useGenericClosureyyq_xXEr0_lF
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$ss5Error_pIgzo_ytytsAA_pIegnrzo_TR
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: function_ref @$s22closure_lifetime_fixup25useGenericClosureThrowingyyq_xKXEKr0_lF
+public func captureClosure<T, V>(c : (T) ->V, d: (T) -> V, t: T) throws {
+ useClosure {
+ c(t)
+ d(t)
+ }
+
+ try useClosureThrowing {
+ c(t)
+ d(t)
+ }
+
+ useGenericClosure {
+ c(t)
+ d(t)
+ }
+
+ try useGenericClosureThrowing {
+ c(t)
+ d(t)
+ }
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup16captureResilient
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+
+public func captureResilient(c: Size) throws {
+ useClosure {
+ c.method()
+ }
+
+ try useClosureThrowing {
+ c.method()
+ }
+
+ useGenericClosure {
+ c.method()
+ }
+
+ try useGenericClosureThrowing {
+ c.method()
+ }
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup10capturePOD1cy16resilient_struct5PointV_tKF
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+public func capturePOD(c: Point) throws {
+ useClosure {
+ c.method()
+ }
+
+ try useClosureThrowing {
+ c.method()
+ }
+
+ useGenericClosure {
+ c.method()
+ }
+
+ try useGenericClosureThrowing {
+ c.method()
+ }
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup11captureEnum
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+public func captureEnum(c: FullyFixedLayout, d: CustomColor) throws {
+ useClosure {
+ _ = c
+ _ = d
+ }
+
+ try useClosureThrowing {
+ _ = c
+ _ = d
+ }
+
+ useGenericClosure {
+ _ = c
+ _ = d
+ }
+
+ try useGenericClosureThrowing {
+ _ = c
+ _ = d
+ }
+}
+
+public protocol EmptyP {}
+
+public struct AddressOnlyStruct : EmptyP {}
+
+public enum AddressOnlyEnum {
+ case nought
+ case mere(EmptyP)
+ case phantom(AddressOnlyStruct)
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup22captureAddressOnlyEnum
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+public func captureAddressOnlyEnum(c: AddressOnlyEnum, d: AddressOnlyEnum) throws {
+ useClosure {
+ _ = c
+ _ = d
+ }
+
+ try useClosureThrowing {
+ _ = c
+ _ = d
+ }
+
+ useGenericClosure {
+ _ = c
+ _ = d
+ }
+
+ try useGenericClosureThrowing {
+ _ = c
+ _ = d
+ }
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup15captureProtocol
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+public func captureProtocol(c: EmptyP, d: EmptyP) throws {
+ useClosure {
+ _ = c
+ _ = d
+ }
+
+ try useClosureThrowing {
+ _ = c
+ _ = d
+ }
+
+ useGenericClosure { () -> Int in
+ _ = c
+ _ = d
+ return 0
+ }
+
+ try useGenericClosureThrowing { () -> Int in
+ _ = c
+ _ = d
+ return 0
+ }
+}
+
+public protocol Q {
+ associatedtype Element
+ func test<U>(_ c: (Element) -> U) throws
+}
+
+// CHECK-LABEL: sil @$s22closure_lifetime_fixup0A18WithAssociatedType1c1eyx_7ElementQztKAA1QRzlF
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: try_apply
+public func closureWithAssociatedType<C : Q> (c: C, e: C.Element) throws {
+ try c.test( { _ in _ = e })
+}
+
+
+public class F<T> {
+ func test<V>(_ c: (V) throws -> T) {}
+ let t : T? = nil
+}
+
+// CHECK-LABEL: s22closure_lifetime_fixup22testClosureMethodParam1fyAA1FCyxG_tKlF
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: partial_apply [callee_guaranteed] [on_stack]
+// CHECK: apply
+public func testClosureMethodParam<T>(f: F<T>) throws {
+ try f.test { return f.t! }
+}
diff --git a/test/SILOptimizer/closure_specialize.sil b/test/SILOptimizer/closure_specialize.sil
index 5bc8e7d..6abcaba 100644
--- a/test/SILOptimizer/closure_specialize.sil
+++ b/test/SILOptimizer/closure_specialize.sil
@@ -808,3 +808,23 @@
release_value %2 : $@callee_guaranteed () -> Int
return %value : $Int
}
+// CHECK-LABEL: sil @reabstractionTest_on_stack
+// CHECK: bb0([[A:%.*]] : $Int):
+// CHECK: [[R:%.*]] = alloc_stack $Int
+// CHECK: [[F:%.*]] = function_ref @$s25testClosureThunkNoEscape20aB14ConvertHelper2SiTf1nc_n
+// CHECK: apply [[F]]([[R]], [[A]])
+sil @reabstractionTest_on_stack : $(Int) -> () {
+bb0(%0 : $Int):
+ %48 = alloc_stack $Int
+ %49 = function_ref @testClosureConvertHelper2 : $@convention(thin) (Int) -> Int
+ %50 = partial_apply [callee_guaranteed] [on_stack] %49(%0) : $@convention(thin) (Int) -> Int
+ %52 = function_ref @reabstractionThunk : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
+ %53 = partial_apply [callee_guaranteed] [on_stack] %52(%50) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
+ %55 = function_ref @testClosureThunkNoEscape2 : $@convention(thin) (@noescape @callee_guaranteed () -> @out Int) -> @out Int
+ apply %55(%48, %53) : $@convention(thin) (@noescape @callee_guaranteed () -> @out Int) -> @out Int
+ dealloc_stack %53 : $@noescape @callee_guaranteed () -> @out Int
+ dealloc_stack %50 : $@noescape @callee_guaranteed () -> Int
+ dealloc_stack %48 : $*Int
+ %empty = tuple ()
+ return %empty : $()
+}
diff --git a/test/SILOptimizer/inout_deshadow_integration.swift b/test/SILOptimizer/inout_deshadow_integration.swift
index cb26378..615930c 100644
--- a/test/SILOptimizer/inout_deshadow_integration.swift
+++ b/test/SILOptimizer/inout_deshadow_integration.swift
@@ -94,7 +94,7 @@
// CHECK-LABEL: sil hidden @$s26inout_deshadow_integration24StructWithMutatingMethodV08mutatingG0{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout StructWithMutatingMethod) -> () {
// CHECK-NOT: alloc_box
-// CHECK-NOT: alloc_stack
+// CHECK-NOT: alloc_stack $
// CHECK: }
// CHECK-LABEL: sil hidden @$s26inout_deshadow_integration24StructWithMutatingMethodV28testStandardLibraryOperators{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout StructWithMutatingMethod) -> () {
diff --git a/test/SILOptimizer/mandatory_inlining.sil b/test/SILOptimizer/mandatory_inlining.sil
index db99d67..6aee6a0 100644
--- a/test/SILOptimizer/mandatory_inlining.sil
+++ b/test/SILOptimizer/mandatory_inlining.sil
@@ -1184,3 +1184,23 @@
%3 = apply %2() : $@noescape () -> Builtin.Int32
return %3 : $Builtin.Int32
}
+
+// CHECK-LABEL: sil @test_guaranteed_on_stack_closure
+// CHECK: strong_retain %0 : $C
+// CHECK: [[F:%.*]] = function_ref @use_c : $@convention(thin) (@guaranteed C) -> ()
+// CHECK: apply [[F]](%0) : $@convention(thin) (@guaranteed C) -> ()
+// CHECK: strong_release %0 : $C
+// CHECK-NOT: strong_release
+// CHECK: return
+sil @test_guaranteed_on_stack_closure : $@convention(thin) (@guaranteed C) -> () {
+bb0(%0: $C):
+ strong_retain %0 : $C
+ %closure_fun = function_ref @guaranteed_closure_func : $@convention(thin) (@guaranteed C) -> ()
+ %closure = partial_apply [on_stack] [callee_guaranteed] %closure_fun(%0) : $@convention(thin) (@guaranteed C) -> ()
+ %closure2 = mark_dependence %closure : $@noescape @callee_guaranteed () -> () on %0 : $C
+ apply %closure2() : $@noescape @callee_guaranteed () -> ()
+ strong_release %0: $C
+ dealloc_stack %closure : $@noescape @callee_guaranteed () -> ()
+ %tuple = tuple()
+ return %tuple : $()
+}
diff --git a/test/SILOptimizer/predictable_deadalloc_elim.sil b/test/SILOptimizer/predictable_deadalloc_elim.sil
new file mode 100644
index 0000000..7e40d5a
--- /dev/null
+++ b/test/SILOptimizer/predictable_deadalloc_elim.sil
@@ -0,0 +1,267 @@
+// RUN: %target-sil-opt -enable-sil-verify-all %s -predictable-deadalloc-elim | %FileCheck %s
+
+sil_stage canonical
+
+import Swift
+import Builtin
+
+// CHECK-LABEL: sil @simple_trivial_stack : $@convention(thin) (Builtin.Int32) -> () {
+// CHECK-NOT: alloc_stack
+// CHECK: } // end sil function 'simple_trivial_stack'
+sil @simple_trivial_stack : $@convention(thin) (Builtin.Int32) -> () {
+bb0(%0 : $Builtin.Int32):
+ %1 = alloc_stack $Builtin.Int32
+ store %0 to %1 : $*Builtin.Int32
+ dealloc_stack %1 : $*Builtin.Int32
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK-LABEL: sil @simple_trivial_init_box : $@convention(thin) (Builtin.Int32) -> () {
+// CHECK-NOT: alloc_box
+// CHECK: } // end sil function 'simple_trivial_init_box'
+sil @simple_trivial_init_box : $@convention(thin) (Builtin.Int32) -> () {
+bb0(%0 : $Builtin.Int32):
+ %1 = alloc_box ${ var Builtin.Int32 }
+ %2 = project_box %1 : ${ var Builtin.Int32 }, 0
+ store %0 to %2 : $*Builtin.Int32
+ strong_release %1 : ${ var Builtin.Int32 }
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK-LABEL: sil @simple_trivial_uninit_box : $@convention(thin) (Builtin.Int32) -> () {
+// CHECK-NOT: alloc_box
+// CHECK: } // end sil function 'simple_trivial_uninit_box'
+sil @simple_trivial_uninit_box : $@convention(thin) (Builtin.Int32) -> () {
+bb0(%0 : $Builtin.Int32):
+ %1 = alloc_box ${ var Builtin.Int32 }
+ %2 = project_box %1 : ${ var Builtin.Int32 }, 0
+ store %0 to %2 : $*Builtin.Int32
+ dealloc_box %1 : ${ var Builtin.Int32 }
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK-LABEL: sil @simple_nontrivial_stack : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: bb0([[ARG:%.*]] :
+// CHECK-NEXT: strong_release [[ARG]]
+// CHECK-NEXT: tuple
+// CHECK-NEXT: return
+// CHECK: } // end sil function 'simple_nontrivial_stack'
+sil @simple_nontrivial_stack : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ %1 = alloc_stack $Builtin.NativeObject
+ store %0 to %1 : $*Builtin.NativeObject
+ destroy_addr %1 : $*Builtin.NativeObject
+ dealloc_stack %1 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// We do not handle this today, since we do not understand that we need to treat
+// the strong_release of the alloc_box as a destroy_addr of the entire value.
+//
+// FIXME: We should be able to handle this.
+//
+// CHECK-LABEL: sil @simple_nontrivial_init_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: alloc_box
+// CHECK: } // end sil function 'simple_nontrivial_init_box'
+sil @simple_nontrivial_init_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ %1 = alloc_box ${ var Builtin.NativeObject }
+ %2 = project_box %1 : ${ var Builtin.NativeObject }, 0
+ store %0 to %2 : $*Builtin.NativeObject
+ strong_release %1 : ${ var Builtin.NativeObject }
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK-LABEL: sil @simple_nontrivial_uninit_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: bb0([[ARG:%.*]] :
+// CHECK-NEXT: strong_release [[ARG]]
+// CHECK-NEXT: tuple
+// CHECK-NEXT: return
+// CHECK: } // end sil function 'simple_nontrivial_uninit_box'
+sil @simple_nontrivial_uninit_box : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ %1 = alloc_box ${ var Builtin.NativeObject }
+ %2 = project_box %1 : ${ var Builtin.NativeObject }, 0
+ store %0 to %2 : $*Builtin.NativeObject
+ destroy_addr %2 : $*Builtin.NativeObject
+ dealloc_box %1 : ${ var Builtin.NativeObject }
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+//////////////////
+// Assign Tests //
+//////////////////
+
+// Make sure that we do eliminate this allocation
+// CHECK-LABEL: sil @simple_assign_take_trivial : $@convention(thin) (Builtin.Int32, @in Builtin.Int32) -> () {
+// CHECK-NOT: alloc_stack
+// CHECK: } // end sil function 'simple_assign_take_trivial'
+sil @simple_assign_take_trivial : $@convention(thin) (Builtin.Int32, @in Builtin.Int32) -> () {
+bb0(%0 : $Builtin.Int32, %1 : $*Builtin.Int32):
+ %2 = alloc_stack $Builtin.Int32
+ store %0 to %2 : $*Builtin.Int32
+ copy_addr [take] %1 to %2 : $*Builtin.Int32
+ dealloc_stack %2 : $*Builtin.Int32
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// In this case, we perform an init, copy. Since we do not want to lose the +1
+// on the argument, we do not eliminate this (even though with time perhaps we
+// could).
+// CHECK-LABEL: sil @simple_init_copy : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+// CHECK: alloc_stack
+// CHECK: copy_addr
+// CHECK: } // end sil function 'simple_init_copy'
+sil @simple_init_copy : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
+ %2 = alloc_stack $Builtin.NativeObject
+ store %0 to %2 : $*Builtin.NativeObject
+ destroy_addr %2 : $*Builtin.NativeObject
+ copy_addr %1 to [initialization] %2 : $*Builtin.NativeObject
+ destroy_addr %2 : $*Builtin.NativeObject
+ dealloc_stack %2 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// This we can promote successfully.
+// CHECK-LABEL: sil @simple_init_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $*Builtin.NativeObject):
+// CHECK-NOT: alloc_stack
+// CHECK: strong_release [[ARG0]]
+// CHECK: [[ARG1_LOADED:%.*]] = load [[ARG1]]
+// CHECK: strong_release [[ARG1_LOADED]]
+// CHECK: } // end sil function 'simple_init_take'
+sil @simple_init_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
+ %2 = alloc_stack $Builtin.NativeObject
+ store %0 to %2 : $*Builtin.NativeObject
+ destroy_addr %2 : $*Builtin.NativeObject
+ copy_addr [take] %1 to [initialization] %2 : $*Builtin.NativeObject
+ destroy_addr %2 : $*Builtin.NativeObject
+ dealloc_stack %2 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// Since we are copying the input argument, we can not get rid of the copy_addr,
+// meaning we shouldn't eliminate the allocation here.
+// CHECK-LABEL: sil @simple_assign_no_take : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+// CHECK: alloc_stack
+// CHECK: copy_addr
+// CHECK: } // end sil function 'simple_assign_no_take'
+sil @simple_assign_no_take : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
+ %2 = alloc_stack $Builtin.NativeObject
+ store %0 to %2 : $*Builtin.NativeObject
+ copy_addr %1 to %2 : $*Builtin.NativeObject
+ destroy_addr %2 : $*Builtin.NativeObject
+ dealloc_stack %2 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// If PMO understood how to promote assigns, we should be able to handle this
+// case.
+// CHECK-LABEL: sil @simple_assign_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
+// CHECK: alloc_stack
+// CHECK: copy_addr
+// CHECK: } // end sil function 'simple_assign_take'
+sil @simple_assign_take : $@convention(thin) (@owned Builtin.NativeObject, @in Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
+ %2 = alloc_stack $Builtin.NativeObject
+ store %0 to %2 : $*Builtin.NativeObject
+ copy_addr [take] %1 to %2 : $*Builtin.NativeObject
+ destroy_addr %2 : $*Builtin.NativeObject
+ dealloc_stack %2 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// CHECK-LABEL: sil @simple_diamond_without_assign : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: bb0([[ARG:%.*]] :
+// CHECK-NOT: alloc_stack
+// CHECK-NOT: store
+// CHECK: bb3:
+// CHECK-NEXT: strong_release [[ARG]]
+// CHECK: } // end sil function 'simple_diamond_without_assign'
+sil @simple_diamond_without_assign : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ %1 = alloc_stack $Builtin.NativeObject
+ store %0 to %1 : $*Builtin.NativeObject
+ cond_br undef, bb1, bb2
+
+bb1:
+ br bb3
+
+bb2:
+ br bb3
+
+bb3:
+ destroy_addr %1 : $*Builtin.NativeObject
+ dealloc_stack %1 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// We should not promote this due to this being an assign to %2.
+// CHECK-LABEL: sil @simple_diamond_with_assign : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+// CHECK: alloc_stack
+// CHECK: copy_addr
+// CHECK: } // end sil function 'simple_diamond_with_assign'
+sil @simple_diamond_with_assign : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
+ %2 = alloc_stack $Builtin.NativeObject
+ store %0 to %2 : $*Builtin.NativeObject
+ cond_br undef, bb1, bb2
+
+bb1:
+ copy_addr [take] %1 to %2 : $*Builtin.NativeObject
+ br bb3
+
+bb2:
+ br bb3
+
+bb3:
+ destroy_addr %2 : $*Builtin.NativeObject
+ dealloc_stack %2 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// Today PMO can not handle different available values coming from different
+// BBs. With time it can be taught to do that if necessary. That being said,
+// this test shows that we /tried/ and failed with the available value test
+// instead of failing earlier due to the copy_addr being an assign since we
+// explode the copy_addr.
+// CHECK-LABEL: sil @simple_diamond_with_assign_remove : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+// CHECK: alloc_stack
+// CHECK-NOT: copy_addr
+// CHECK: } // end sil function 'simple_diamond_with_assign_remove'
+sil @simple_diamond_with_assign_remove : $@convention(thin) (@owned Builtin.NativeObject, @in_guaranteed Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject, %1 : $*Builtin.NativeObject):
+ %2 = alloc_stack $Builtin.NativeObject
+ store %0 to %2 : $*Builtin.NativeObject
+ cond_br undef, bb1, bb2
+
+bb1:
+ destroy_addr %2 : $*Builtin.NativeObject
+ copy_addr [take] %1 to [initialization] %2 : $*Builtin.NativeObject
+ br bb3
+
+bb2:
+ br bb3
+
+bb3:
+ destroy_addr %2 : $*Builtin.NativeObject
+ dealloc_stack %2 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
diff --git a/test/SILOptimizer/predictable_memopt.sil b/test/SILOptimizer/predictable_memopt.sil
index 407beac..63f6154 100644
--- a/test/SILOptimizer/predictable_memopt.sil
+++ b/test/SILOptimizer/predictable_memopt.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -enable-sil-verify-all %s -predictable-memopt | %FileCheck %s
+// RUN: %target-sil-opt -enable-sil-verify-all %s -predictable-memaccess-opts -predictable-deadalloc-elim | %FileCheck %s
import Builtin
import Swift
diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil
index ed3c25c..4c9a54f 100644
--- a/test/SILOptimizer/sil_combine_apply.sil
+++ b/test/SILOptimizer/sil_combine_apply.sil
@@ -571,3 +571,68 @@
%999 = tuple ()
return %999 : $()
}
+
+// CHECK-LABEL: sil shared @applied_on_stack : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[F:%.*]] = function_ref @indirectClosure : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
+// CHECK: [[STK:%.*]] = alloc_stack $Builtin.Int64
+// CHECK: [[STK2:%.*]] = alloc_stack $Builtin.Int64
+// CHECK: [[I:%.*]] = integer_literal $Builtin.Int64, 3
+// CHECK: store [[I]] to [[STK2]] : $*Builtin.Int64
+// CHECK: apply [[F]]([[STK]], [[STK2]]) : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
+// CHECK: dealloc_stack [[STK2]] : $*Builtin.Int64
+// CHECK: dealloc_stack [[STK]] : $*Builtin.Int64
+// CHECK: return %8 : $()
+
+sil shared @applied_on_stack : $@convention(thin) () -> () {
+bb0:
+ %fn = function_ref @indirectClosure : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
+ %pa = partial_apply [callee_guaranteed] [on_stack] %fn() : $@convention(thin) (@in Builtin.Int64) -> @out Builtin.Int64
+ %out = alloc_stack $Builtin.Int64
+ %in = alloc_stack $Builtin.Int64
+ %c3 = integer_literal $Builtin.Int64, 3
+ store %c3 to %in : $*Builtin.Int64
+ %call = apply %pa(%out, %in) : $@noescape @callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64
+ dealloc_stack %in : $*Builtin.Int64
+ dealloc_stack %out : $*Builtin.Int64
+ dealloc_stack %pa : $@noescape @callee_guaranteed (@in Builtin.Int64) -> @out Builtin.Int64
+ %999 = tuple ()
+ return %999 : $()
+}
+
+sil @guaranteed_closure_throws2 : $@convention(thin) (Builtin.Int32, @guaranteed C) -> @error Error
+
+// CHECK-LABEL: sil @test_guaranteed_closure_try_apply_on_stack
+// CHECK: bb0
+// CHECK: strong_retain
+// CHECK: strong_retain
+// CHECK: try_apply
+// CHECK: bb1
+// CHECK: strong_release
+// CHECK: strong_release
+// CHECK: br bb3
+// CHECK: bb2
+// CHECK: strong_release
+// CHECK: strong_release
+// CHECK: br bb3
+sil @test_guaranteed_closure_try_apply_on_stack : $@convention(thin) (@guaranteed C, Builtin.Int32) -> () {
+bb0(%0: $C, %1: $Builtin.Int32):
+ strong_retain %0 : $C
+ %closure_fun = function_ref @guaranteed_closure_throws2 : $@convention(thin) (Builtin.Int32, @guaranteed C) -> @error Error
+ %closure = partial_apply [callee_guaranteed] [on_stack] %closure_fun(%0) : $@convention(thin) (Builtin.Int32, @guaranteed C) -> @error Error
+ try_apply %closure(%1) : $@noescape @callee_guaranteed (Builtin.Int32) -> @error Error, normal bb7, error bb11
+
+bb7(%callret : $()):
+ dealloc_stack %closure : $@noescape @callee_guaranteed (Builtin.Int32) -> @error Error
+ strong_release %0: $C
+ br bb99
+
+bb11(%128 : $Error):
+ dealloc_stack %closure : $@noescape @callee_guaranteed (Builtin.Int32) -> @error Error
+ strong_release %0: $C
+ br bb99
+
+bb99:
+ %t = tuple()
+ return %t : $()
+}
diff --git a/test/SILOptimizer/simplify_cfg.sil b/test/SILOptimizer/simplify_cfg.sil
index ba6cbe8..f458a34 100644
--- a/test/SILOptimizer/simplify_cfg.sil
+++ b/test/SILOptimizer/simplify_cfg.sil
@@ -2483,10 +2483,12 @@
sil @non_throwing_closure : $@convention(thin) (Int) -> Int
// CHECK-LABEL: sil @replace_try_apply_with_apply
-// CHECK: [[R:%[0-9]+]] = apply [nothrow] %0(%{{[0-9]+}}) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error)
+// CHECK: [[R:%[0-9]+]] = apply [nothrow] %1(%{{[0-9]+}}) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error)
+// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: return [[R]] : $Int
sil @replace_try_apply_with_apply : $@convention(thin) () -> Int {
bb0:
+ %as = alloc_stack $Builtin.Int32
%0 = function_ref @rethrow_function : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error)
%1 = function_ref @non_throwing_closure : $@convention(thin) (Int) -> Int
%2 = thin_to_thick_function %1 : $@convention(thin) (Int) -> Int to $@callee_owned (Int) -> Int
@@ -2494,9 +2496,11 @@
try_apply %0(%3) : $@convention(thin) (@owned @callee_owned (Int) -> (Int, @error Error)) -> (Int, @error Error), normal bb1, error bb2
bb1(%5 : $Int):
+ dealloc_stack %as: $*Builtin.Int32
return %5 : $Int
bb2(%8 : $Error):
+ dealloc_stack %as: $*Builtin.Int32
unreachable
}
diff --git a/test/Sanitizers/asan.swift b/test/Sanitizers/asan.swift
index 9768fa7..68334f6 100644
--- a/test/Sanitizers/asan.swift
+++ b/test/Sanitizers/asan.swift
@@ -4,6 +4,9 @@
// REQUIRES: executable_test
// REQUIRES: asan_runtime
+// rdar://problem/47367694 tracks re-enabling this test for backward deployment.
+// UNSUPPORTED: remote_run
+
// Make sure we can handle swifterror. LLVM's address sanitizer pass needs to
// ignore swifterror addresses.
diff --git a/test/Sanitizers/tsan.swift b/test/Sanitizers/tsan.swift
index a9cfe9f..512bef2 100644
--- a/test/Sanitizers/tsan.swift
+++ b/test/Sanitizers/tsan.swift
@@ -4,6 +4,7 @@
// REQUIRES: executable_test
// REQUIRES: tsan_runtime
// UNSUPPORTED: OS=tvos
+// UNSUPPORTED: CPU=powerpc64le
// FIXME: This should be covered by "tsan_runtime"; older versions of Apple OSs
// don't support TSan.
diff --git a/test/Serialization/sil_partial_apply_ownership.sil b/test/Serialization/sil_partial_apply_ownership.sil
index 221d2ae..ac6ef32 100644
--- a/test/Serialization/sil_partial_apply_ownership.sil
+++ b/test/Serialization/sil_partial_apply_ownership.sil
@@ -62,3 +62,17 @@
%t = tuple ()
return %t : $()
}
+
+// CHECK-LABEL: sil @partial_apply_on_stack
+// CHECK: partial_apply [callee_guaranteed] [on_stack] %{{.*}} : $@convention(thin) (Builtin.Int64) -> ()
+sil @partial_apply_on_stack : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @subject : $@convention(thin) (Builtin.Int64) -> ()
+ %z = integer_literal $Builtin.Int64, 0
+ %c = partial_apply [callee_guaranteed] [on_stack] %f(%z) : $@convention(thin) (Builtin.Int64) -> ()
+ %f2 = function_ref @use : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ apply %f2(%c) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ dealloc_stack %c : $@noescape @callee_guaranteed () -> ()
+ %t = tuple ()
+ return %t : $()
+}
diff --git a/test/Syntax/Inputs/invalid.sed b/test/Syntax/Inputs/invalid.sed
new file mode 100644
index 0000000..41894dd
--- /dev/null
+++ b/test/Syntax/Inputs/invalid.sed
@@ -0,0 +1,32 @@
+
+# [0xC2] is utf8 2 byte character start byte.
+# 0xC2 without second byte is invalid UTF-8 sequence.
+# It becomes garbage text trivia.
+# Marker(1) is replaced to this sequence.
+s/Z1/Â/g
+
+# [0xCC, 0x82] in UTF-8 is U+0302.
+# This character is invalid for identifier start, but valid for identifier body.
+# It becomes unknown token.
+# If this type characters are conitguous, they are concatenated to one long unknown token.
+# Marker(2) is replaced to this sequence.
+s/Z2/̂/g
+
+# [0xE2, 0x80, 0x9C] in UTF-8 is U+201C, left quote.
+# It becomes single character unknown token.
+# If this left quote and right quote enclosure text,
+# they become one long unknown token.
+# Marker(3) is replaced to this sequence.
+s/Z3/“/g
+
+# [0xE2, 0x80, 0x9D] in UTF-8 is U+201D, right quote.
+# It becomes single character unknown token.
+# Marker(4) is replaced to this sequence.
+s/Z4/”/g
+
+# [0xE1, 0x9A, 0x80] in UTF-8 is U+1680.
+# This character is invalid for swift source.
+# It becomes garbage trivia.
+# Marker(5) is replaced to this sequence.
+s/Z5/ /g
+
diff --git a/test/Syntax/Inputs/nbsp.sed b/test/Syntax/Inputs/nbsp.sed
new file mode 100644
index 0000000..3d9adf5
--- /dev/null
+++ b/test/Syntax/Inputs/nbsp.sed
@@ -0,0 +1 @@
+s/Z/ /g
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index 2c1af8b..512ca73 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -51,7 +51,8 @@
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ArrayExpr>[<ArrayElement><FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr>, </ArrayElement><ArrayElement><FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr>, </ArrayElement><ArrayElement><FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr>, </ArrayElement><ArrayElement><FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr></ArrayElement>]</ArrayExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <FunctionCallExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr></DictionaryElement>]</DictionaryExpr></SequenceExpr><FunctionCallExpr><IdentifierExpr>
foo</IdentifierExpr>(<FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr></FunctionCallArgument>)</FunctionCallExpr><SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><DotSelfExpr><FunctionCallExpr><IdentifierExpr>type</IdentifierExpr>(<FunctionCallArgument>of: <IdentifierExpr>a</IdentifierExpr></FunctionCallArgument>)</FunctionCallExpr>.self</DotSelfExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><FunctionCallExpr><IdentifierExpr>type</IdentifierExpr>(<FunctionCallArgument>of: <IdentifierExpr>a</IdentifierExpr></FunctionCallArgument>)</FunctionCallExpr>.self</MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IdentifierExpr>a</IdentifierExpr>.`self`</MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>A </IdentifierExpr><ArrowExpr>-> </ArrowExpr><MemberAccessExpr><IdentifierExpr>B</IdentifierExpr>.C</MemberAccessExpr><BinaryOperatorExpr><</BinaryOperatorExpr><PostfixUnaryExpr><IdentifierExpr>Int</IdentifierExpr>></PostfixUnaryExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><ArrayExpr>[<ArrayElement><SequenceExpr><TupleExpr>(<TupleElement><IdentifierExpr>A</IdentifierExpr></TupleElement>) </TupleExpr><ArrowExpr>throws -> </ArrowExpr><IdentifierExpr>B</IdentifierExpr></SequenceExpr></ArrayElement>]</ArrayExpr>()</FunctionCallExpr></SequenceExpr>
}</CodeBlock></FunctionDecl></MemberDeclListItem><MemberDeclListItem><FunctionDecl>
@@ -90,11 +91,11 @@
}</CodeBlock></FunctionDecl></MemberDeclListItem><MemberDeclListItem><FunctionDecl>
func implictMember<FunctionSignature><ParameterClause>() </ParameterClause></FunctionSignature><CodeBlock>{<SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ImplicitMemberExpr>.foo</ImplicitMemberExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><ImplicitMemberExpr>.foo</ImplicitMemberExpr>(<FunctionCallArgument>x: <IntegerLiteralExpr>12</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><ImplicitMemberExpr>.foo </ImplicitMemberExpr><ClosureExpr>{ <IntegerLiteralExpr>12 </IntegerLiteralExpr>}</ClosureExpr></FunctionCallExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><SubscriptExpr><ImplicitMemberExpr>.foo</ImplicitMemberExpr>[<FunctionCallArgument><IntegerLiteralExpr>12</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><ImplicitMemberExpr>.foo</ImplicitMemberExpr>.bar</MemberAccessExpr></SequenceExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr>.foo</MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><MemberAccessExpr>.foo</MemberAccessExpr>(<FunctionCallArgument>x: <IntegerLiteralExpr>12</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><MemberAccessExpr>.foo </MemberAccessExpr><ClosureExpr>{ <IntegerLiteralExpr>12 </IntegerLiteralExpr>}</ClosureExpr></FunctionCallExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><SubscriptExpr><MemberAccessExpr>.foo</MemberAccessExpr>[<FunctionCallArgument><IntegerLiteralExpr>12</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><MemberAccessExpr>.foo</MemberAccessExpr>.bar</MemberAccessExpr></SequenceExpr>
}</CodeBlock></FunctionDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl>
init<ParameterClause>() </ParameterClause><CodeBlock>{}</CodeBlock></InitializerDecl></MemberDeclListItem><MemberDeclListItem><InitializerDecl><Attribute>
@@ -264,8 +265,8 @@
foo</IdentifierExpr>[<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr><SubscriptExpr><IdentifierExpr>
foo</IdentifierExpr>[] <ClosureExpr>{}</ClosureExpr></SubscriptExpr><SubscriptExpr><IdentifierExpr>
foo</IdentifierExpr>[<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>] <ClosureExpr>{}</ClosureExpr></SubscriptExpr><SubscriptExpr><SubscriptExpr><IdentifierExpr>
- foo</IdentifierExpr>[<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr>[<FunctionCallArgument><IntegerLiteralExpr>2</IntegerLiteralExpr>,</FunctionCallArgument><FunctionCallArgument>x:<IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr><DotSelfExpr><FunctionCallExpr><ForcedValueExpr><MemberAccessExpr><PostfixUnaryExpr><OptionalChainingExpr><IdentifierExpr>
- foo</IdentifierExpr>?</OptionalChainingExpr>++</PostfixUnaryExpr>.bar</MemberAccessExpr>!</ForcedValueExpr>(<FunctionCallArgument><IdentifierExpr>baz</IdentifierExpr></FunctionCallArgument>)</FunctionCallExpr>.self</DotSelfExpr><MemberAccessExpr><FunctionCallExpr><IdentifierExpr>
+ foo</IdentifierExpr>[<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr>[<FunctionCallArgument><IntegerLiteralExpr>2</IntegerLiteralExpr>,</FunctionCallArgument><FunctionCallArgument>x:<IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr><MemberAccessExpr><FunctionCallExpr><ForcedValueExpr><MemberAccessExpr><PostfixUnaryExpr><OptionalChainingExpr><IdentifierExpr>
+ foo</IdentifierExpr>?</OptionalChainingExpr>++</PostfixUnaryExpr>.bar</MemberAccessExpr>!</ForcedValueExpr>(<FunctionCallArgument><IdentifierExpr>baz</IdentifierExpr></FunctionCallArgument>)</FunctionCallExpr>.self</MemberAccessExpr><MemberAccessExpr><FunctionCallExpr><IdentifierExpr>
foo</IdentifierExpr>()</FunctionCallExpr>.0</MemberAccessExpr><MemberAccessExpr><SpecializeExpr><IdentifierExpr>
foo</IdentifierExpr><GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Int</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SpecializeExpr>.bar</MemberAccessExpr><FunctionCallExpr><SpecializeExpr><IdentifierExpr>
foo</IdentifierExpr><GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Int</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SpecializeExpr>()</FunctionCallExpr><FunctionCallExpr><SpecializeExpr><MemberAccessExpr><IdentifierExpr>
@@ -273,7 +274,7 @@
foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></IdentifierExpr>()</FunctionCallExpr><FunctionCallExpr><SpecializeExpr><IdentifierExpr>
foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument>)</DeclNameArguments></IdentifierExpr><GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Int</SimpleTypeIdentifier></GenericArgument>> </GenericArgumentClause></SpecializeExpr><ClosureExpr>{ }</ClosureExpr></FunctionCallExpr><SequenceExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ImplicitMemberExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></ImplicitMemberExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IdentifierExpr>x</IdentifierExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><IdentifierExpr>foo</IdentifierExpr>(<FunctionCallArgument><InOutExpr>&<IdentifierExpr>d</IdentifierExpr></InOutExpr></FunctionCallArgument>)</FunctionCallExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><EditorPlaceholderExpr><#Placeholder#> </EditorPlaceholderExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><EditorPlaceholderExpr><#T##(Int) -> Int#></EditorPlaceholderExpr></SequenceExpr>
@@ -318,7 +319,7 @@
case <CaseItem><ValueBindingPattern>let <ExpressionPattern><TupleExpr>(<TupleElement><UnresolvedPatternExpr><IdentifierPattern>a</IdentifierPattern></UnresolvedPatternExpr>, </TupleElement><TupleElement><UnresolvedPatternExpr><IdentifierPattern>b</IdentifierPattern></UnresolvedPatternExpr></TupleElement>)</TupleExpr></ExpressionPattern></ValueBindingPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
case <CaseItem><ExpressionPattern><TupleExpr>(<TupleElement><UnresolvedPatternExpr><ValueBindingPattern>let <IdentifierPattern>a</IdentifierPattern></ValueBindingPattern></UnresolvedPatternExpr>, </TupleElement><TupleElement><UnresolvedPatternExpr><ValueBindingPattern>var <IdentifierPattern>b</IdentifierPattern></ValueBindingPattern></UnresolvedPatternExpr></TupleElement>)</TupleExpr></ExpressionPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
case <CaseItem><IsTypePattern>is <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></IsTypePattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
- case <CaseItem><ValueBindingPattern>let <ExpressionPattern><FunctionCallExpr><ImplicitMemberExpr>.bar</ImplicitMemberExpr>(<FunctionCallArgument><UnresolvedPatternExpr><IdentifierPattern>x</IdentifierPattern></UnresolvedPatternExpr></FunctionCallArgument>)</FunctionCallExpr></ExpressionPattern></ValueBindingPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
+ case <CaseItem><ValueBindingPattern>let <ExpressionPattern><FunctionCallExpr><MemberAccessExpr>.bar</MemberAccessExpr>(<FunctionCallArgument><UnresolvedPatternExpr><IdentifierPattern>x</IdentifierPattern></UnresolvedPatternExpr></FunctionCallArgument>)</FunctionCallExpr></ExpressionPattern></ValueBindingPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
case <CaseItem><ExpressionPattern><MemberAccessExpr><IdentifierExpr>MyEnum</IdentifierExpr>.foo</MemberAccessExpr></ExpressionPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
case <CaseItem><ValueBindingPattern>let <ExpressionPattern><SequenceExpr><UnresolvedPatternExpr><IdentifierPattern>a </IdentifierPattern></UnresolvedPatternExpr><AsExpr>as <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></AsExpr></SequenceExpr></ExpressionPattern></ValueBindingPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase><SwitchCase><SwitchCaseLabel>
case <CaseItem><ValueBindingPattern>let <ExpressionPattern><OptionalChainingExpr><UnresolvedPatternExpr><IdentifierPattern>a</IdentifierPattern></UnresolvedPatternExpr>?</OptionalChainingExpr></ExpressionPattern></ValueBindingPattern></CaseItem>: </SwitchCaseLabel><BreakStmt>break</BreakStmt></SwitchCase>
@@ -384,7 +385,7 @@
case <CaseItem><ValueBindingPattern>let <IdentifierPattern>y</IdentifierPattern></ValueBindingPattern></CaseItem>:</SwitchCaseLabel><BreakStmt>
break</BreakStmt></SwitchCase></IfConfigClause><IfConfigClause>
#else<SwitchCase><SwitchCaseLabel>
- case <CaseItem><ExpressionPattern><FunctionCallExpr><ImplicitMemberExpr>.foo</ImplicitMemberExpr>(<FunctionCallArgument><UnresolvedPatternExpr><ValueBindingPattern>let <IdentifierPattern>x</IdentifierPattern></ValueBindingPattern></UnresolvedPatternExpr></FunctionCallArgument>)</FunctionCallExpr></ExpressionPattern></CaseItem>:</SwitchCaseLabel><BreakStmt>
+ case <CaseItem><ExpressionPattern><FunctionCallExpr><MemberAccessExpr>.foo</MemberAccessExpr>(<FunctionCallArgument><UnresolvedPatternExpr><ValueBindingPattern>let <IdentifierPattern>x</IdentifierPattern></ValueBindingPattern></UnresolvedPatternExpr></FunctionCallArgument>)</FunctionCallExpr></ExpressionPattern></CaseItem>:</SwitchCaseLabel><BreakStmt>
break</BreakStmt></SwitchCase></IfConfigClause>
#endif</IfConfigDecl><SwitchCase><SwitchDefaultLabel>
default:</SwitchDefaultLabel><BreakStmt>
@@ -532,7 +533,7 @@
@_implements(<ImplementsAttributeArguments><SimpleTypeIdentifier>P</SimpleTypeIdentifier>, x</ImplementsAttributeArguments>)</Attribute>
var <PatternBinding><IdentifierPattern>y</IdentifierPattern><TypeAnnotation>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier></TypeAnnotation></PatternBinding></VariableDecl></MemberDeclListItem><MemberDeclListItem><FunctionDecl><Attribute>
@_implements(<ImplementsAttributeArguments><SimpleTypeIdentifier>P</SimpleTypeIdentifier>, g<DeclNameArguments>()</DeclNameArguments></ImplementsAttributeArguments>)</Attribute>
- func h<FunctionSignature><ParameterClause>() </ParameterClause></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl></MemberDeclListItem><MemberDeclListItem><VariableDecl><Attribute>
+ func h<FunctionSignature><ParameterClause>() </ParameterClause></FunctionSignature><CodeBlock>{ <SequenceExpr><DiscardAssignmentExpr>_ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<MemberAccessExpr>.self </MemberAccessExpr></KeyPathExpr></SequenceExpr>}</CodeBlock></FunctionDecl></MemberDeclListItem><MemberDeclListItem><VariableDecl><Attribute>
@available(<AvailabilityArgument>*, </AvailabilityArgument><AvailabilityArgument><AvailabilityLabeledArgument>deprecated: <VersionTuple>1.2</VersionTuple></AvailabilityLabeledArgument>, </AvailabilityArgument><AvailabilityArgument><AvailabilityLabeledArgument>message: "ABC"</AvailabilityLabeledArgument></AvailabilityArgument>)</Attribute><DeclModifier>
fileprivate(set) </DeclModifier>var <PatternBinding><IdentifierPattern>x</IdentifierPattern><TypeAnnotation>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier></TypeAnnotation></PatternBinding></VariableDecl></MemberDeclListItem>
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index b17b017..22cfc0c 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -52,6 +52,7 @@
_ = ["a": bar3(a:1), "b": bar3(a:1), "c": bar3(a:1), "d": bar3(a:1)]
foo(nil, nil, nil)
_ = type(of: a).self
+ _ = a.`self`
_ = A -> B.C<Int>
_ = [(A) throws -> B]()
}
@@ -532,7 +533,7 @@
@_implements(P, x)
var y: String
@_implements(P, g())
- func h() {}
+ func h() { _ = \.self }
@available(*, deprecated: 1.2, message: "ABC")
fileprivate(set) var x: String
diff --git a/test/Syntax/tokens_nonbreaking_space.swift b/test/Syntax/tokens_nonbreaking_space.swift
index 97cd258..b0da4ce 100644
--- a/test/Syntax/tokens_nonbreaking_space.swift
+++ b/test/Syntax/tokens_nonbreaking_space.swift
@@ -1,4 +1,4 @@
-// RUN: cat %s | sed -e 's/'$(echo -ne "\x5a")'/'$(echo -ne "\xc2\xa0")'/g' > %t.tmp
+// RUN: cat %s | sed -f %S/Inputs/nbsp.sed > %t.tmp
// RUN: cp -f %t.tmp %t
// RUN: %swift-syntax-test -input-source-filename %t -dump-full-tokens 2>&1 | %FileCheck %t
let a =Z3Z // nbsp(Z)
diff --git a/test/Syntax/tokens_unknown_and_invalid.swift b/test/Syntax/tokens_unknown_and_invalid.swift
index 98be090..3a5cb16 100644
--- a/test/Syntax/tokens_unknown_and_invalid.swift
+++ b/test/Syntax/tokens_unknown_and_invalid.swift
@@ -5,46 +5,8 @@
// To avoid replace marker in sed command by sed itself,
// marker is also represented in escape sequence.
-// RUN: cat %s | sed \
-
-// [0xC2] is utf8 2 byte character start byte.
-// 0xC2 without second byte is invalid UTF-8 sequence.
-// It becomes garbage text trivia.
-// Marker(1) is replaced to this sequence.
-
-// RUN: -e 's/'$(echo -ne "\x5a1")'/'$(echo -ne "\xc2")'/g' \
-
-// [0xCC, 0x82] in UTF-8 is U+0302.
-// This character is invalid for identifier start, but valid for identifier body.
-// It becomes unknown token.
-// If this type characters are conitguous, they are concatenated to one long unknown token.
-// Marker(2) is replaced to this sequence.
-
-// RUN: -e 's/'$(echo -ne "\x5a2")'/'$(echo -ne "\xcc\x82")'/g' \
-
-// [0xE2, 0x80, 0x9C] in UTF-8 is U+201C, left quote.
-// It becomes single character unknown token.
-// If this left quote and right quote enclosure text,
-// they become one long unknown token.
-// Marker(3) is replaced to this sequence.
-
-// RUN: -e 's/'$(echo -ne "\x5a3")'/'$(echo -ne "\xe2\x80\x9c")'/g' \
-
-// [0xE2, 0x80, 0x9D] in UTF-8 is U+201D, right quote.
-// It becomes single character unknown token.
-// Marker(4) is replaced to this sequence.
-
-// RUN: -e 's/'$(echo -ne "\x5a4")'/'$(echo -ne "\xe2\x80\x9d")'/g' \
-
-// [0xE1, 0x9A, 0x80] in UTF-8 is U+1680.
-// This character is invalid for swift source.
-// It becomes garbage trivia.
-// Marker(5) is replaced to this sequence.
-
-// RUN: -e 's/'$(echo -ne "\x5a5")'/'$(echo -ne "\xe1\x9a\x80")'/g' \
-
-// RUN: > %t
-
+// RUN: cat %s | sed -f %S/Inputs/invalid.sed > %t
+// RUN: %{python} -c "import sys; t = open(sys.argv[1], 'rb').read().replace('\r\n', '\n'); open(sys.argv[1], 'wb').write(t)" %t
// RUN: %swift-syntax-test -input-source-filename %t -dump-full-tokens 2>&1 | %FileCheck %t
// RUN: %round-trip-syntax-test --swift-syntax-test %swift-syntax-test --file %t
@@ -66,20 +28,20 @@
jjj
// Diagnostics
-// CHECK: 52:1: error: invalid UTF-8 found in source file
-// CHECK: 52:7: error: invalid UTF-8 found in source file
-// CHECK: 54:5: error: an identifier cannot begin with this character
-// CHECK: 56:5: error: an identifier cannot begin with this character
-// CHECK: 58:5: error: unicode curly quote found
-// CHECK: 58:8: error: unicode curly quote found
-// CHECK: 60:19: error: unicode curly quote found
-// CHECK: 60:5: error: unicode curly quote found
-// CHECK: 62:5: error: unicode curly quote found
-// CHECK: 65:1: error: invalid character in source file
-// CHECK: 65:9: error: invalid character in source file
+// CHECK: 14:1: error: invalid UTF-8 found in source file
+// CHECK: 14:7: error: invalid UTF-8 found in source file
+// CHECK: 16:5: error: an identifier cannot begin with this character
+// CHECK: 18:5: error: an identifier cannot begin with this character
+// CHECK: 20:5: error: unicode curly quote found
+// CHECK: 20:8: error: unicode curly quote found
+// CHECK: 22:19: error: unicode curly quote found
+// CHECK: 22:5: error: unicode curly quote found
+// CHECK: 24:5: error: unicode curly quote found
+// CHECK: 27:1: error: invalid character in source file
+// CHECK: 27:9: error: invalid character in source file
// Checks around bbb
-// CHECK-LABEL: 52:3
+// CHECK-LABEL: 14:3
// CHECK-NEXT: (Token identifier
// CHECK-NEXT: (trivia newline 1)
// CHECK-NEXT: (trivia garbageText \302)
@@ -89,35 +51,35 @@
// CHECK-NEXT: (trivia garbageText \302))
// Checks around ccc
-// CHECK-LABEL: 54:5
+// CHECK-LABEL: 16:5
// CHECK-NEXT: (Token unknown
// CHECK-NEXT: (text="\xCC\x82"))
// Checks around ddd
-// CHECK-LABEL: 56:5
+// CHECK-LABEL: 18:5
// CHECK-NEXT: (Token unknown
// CHECK-NEXT: (text="\xCC\x82\xCC\x82\xCC\x82\xCC\x82"))
// Checks around eee
-// CHECK-LABEL: 58:5
+// CHECK-LABEL: 20:5
// CHECK-NEXT: (Token unknown
// CHECK-NEXT: (text="\xE2\x80\x9C"))
-// CHECK-LABEL: 58:8
+// CHECK-LABEL: 20:8
// CHECK-NEXT: (Token unknown
// CHECK-NEXT: (text="\xE2\x80\x9C"))
// Checks around fff
-// CHECK-LABEL: 60:5
+// CHECK-LABEL: 22:5
// CHECK-NEXT: (Token unknown
// CHECK-NEXT: (text="\xE2\x80\x9Chello world\xE2\x80\x9D"))
// Checks around ggg
-// CHECK-LABEL: 62:5
+// CHECK-LABEL: 24:5
// CHECK-NEXT: (Token unknown
// CHECK-NEXT: (text="\xE2\x80\x9D"))
// Checks around iii
-// CHECK-LABEL: 65:5
+// CHECK-LABEL: 27:5
// CHECK-NEXT: (Token identifier
// CHECK-NEXT: (trivia newline 1)
// CHECK-NEXT: (trivia garbageText \341\232\200)
diff --git a/test/api-digester/Outputs/stability-stdlib-abi.swift.expected b/test/api-digester/Outputs/stability-stdlib-abi.swift.expected
index f8a2ab1..d06683a 100644
--- a/test/api-digester/Outputs/stability-stdlib-abi.swift.expected
+++ b/test/api-digester/Outputs/stability-stdlib-abi.swift.expected
@@ -71,3 +71,5 @@
Var _NativeSet._storage has declared type change from _RawSetStorage to __RawSetStorage
Var _RawDictionaryStorage.empty has declared type change from _EmptyDictionarySingleton to __EmptyDictionarySingleton
Var _RawSetStorage.empty has declared type change from _EmptySetSingleton to __EmptySetSingleton
+
+Func tryReallocateUniquelyReferenced(buffer:newMinimumCapacity:) has been removed
diff --git a/test/api-digester/Outputs/stability-stdlib-source.swift.expected b/test/api-digester/Outputs/stability-stdlib-source.swift.expected
index e69de29..5678bdb 100644
--- a/test/api-digester/Outputs/stability-stdlib-source.swift.expected
+++ b/test/api-digester/Outputs/stability-stdlib-source.swift.expected
@@ -0,0 +1 @@
+Func tryReallocateUniquelyReferenced(buffer:newMinimumCapacity:) has been removed
diff --git a/test/decl/func/rethrows.swift b/test/decl/func/rethrows.swift
index 86ca746..46de659 100644
--- a/test/decl/func/rethrows.swift
+++ b/test/decl/func/rethrows.swift
@@ -584,3 +584,22 @@
}
Box(unbox: 1) |> suchThat <| { $0 + 1 } // expected-warning {{result of operator '<|' is unused}}
+
+// Constructor delegation -vs- rethrows
+class RethrowingConstructor {
+ init(_ block: () throws -> ()) rethrows {
+ try block()
+ }
+
+ convenience init(bar: Int) {
+ self.init {
+ print("Foo!")
+ }
+ }
+
+ convenience init(baz: Int) throws {
+ try self.init {
+ try throwingFunc()
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/lit.cfg b/test/lit.cfg
index df81bfc..640c926 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -1275,6 +1275,8 @@
config.substitutions.append(('%target-ld', config.target_ld))
if hasattr(config, 'target_cc_options'):
config.substitutions.append(('%target-cc-options', config.target_cc_options))
+else:
+ config.substitutions.append(('%target-cc-options', ''))
config.substitutions.append(
(r'%hardlink-or-copy\(from: *(.*), *to: *(.*)\)',
@@ -1325,7 +1327,7 @@
config.substitutions.append(('%target-swift-modulewrap',
config.target_swift_modulewrap))
-platform_module_dir = make_path(test_resource_dir, '%target-sdk-name', run_cpu)
+platform_module_dir = make_path(test_resource_dir, config.target_sdk_name, run_cpu)
lit_config.note('Using platform module dir: ' + platform_module_dir)
if test_sdk_overlay_dir is not None:
platform_sdk_overlay_dir = make_path(test_sdk_overlay_dir, run_cpu)
diff --git a/test/remote-run/upload-stderr.test-sh b/test/remote-run/upload-stderr.test-sh
index e6a883d..3ed6bd5 100644
--- a/test/remote-run/upload-stderr.test-sh
+++ b/test/remote-run/upload-stderr.test-sh
@@ -1,4 +1,5 @@
REQUIRES: sftp_server
+// XFAIL: CPU=powerpc64le
RUN: %empty-directory(%t)
RUN: %empty-directory(%t/REMOTE/input)
diff --git a/test/stdlib/Compression.swift b/test/stdlib/Compression.swift
new file mode 100644
index 0000000..716874b
--- /dev/null
+++ b/test/stdlib/Compression.swift
@@ -0,0 +1,148 @@
+// RUN: %target-run-simple-swift
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+import StdlibUnittest
+import Compression
+import Foundation
+
+// Read from Data
+class DataSource {
+
+ private var _buf : Data
+ private var _bufSize : Int // total byte count
+ private var _pos : Int // next byte to read
+
+ public init(_ d: Data) {
+ _buf = d
+ _bufSize = d.count
+ _pos = 0
+ }
+
+ public func readData(ofLength len: Int) -> Data? {
+ let n = min(len,_bufSize - _pos)
+ if (n == 0) { return nil } // EOF
+ let d = _buf.subdata(in: _pos ..< _pos + n)
+ _pos += n
+ return d
+ }
+
+}
+
+@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+func ofiltercompress_ifilterdecompress(
+ _ contents: Data, using algo: Algorithm
+) throws -> Bool {
+
+ var payload = Data()
+ var decompressed = Data()
+
+ // Output filter compress
+ let f = DataSource(contents)
+ let ofilter = try OutputFilter(.compress, using: algo) { (x: Data?) -> () in
+ if let x = x { payload.append(x) }
+ }
+ while (true) {
+ let i = f.readData(ofLength: 900)
+ try ofilter.write(i) // will finalize when i is empty
+ if i == nil { break }
+ }
+
+ // Input filter decompress
+ let g = DataSource(payload)
+ let ifilter = try InputFilter(.decompress, using: algo) { (x: Int) -> Data? in
+ return g.readData(ofLength: x)
+ }
+ while let i = try ifilter.readData(ofLength: 400) {
+ decompressed.append(i)
+ }
+
+ print("ofilter | ifilter \(algo): \(contents.count) -> \(payload.count) -> \(decompressed.count)")
+ return contents == decompressed
+}
+
+@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
+func ifiltercompress_ofilterdecompress(
+ _ contents: Data, using algo: Algorithm
+) throws -> Bool {
+
+ var payload = Data()
+ var decompressed = Data()
+
+ // Input filter compress
+ let f = DataSource(contents)
+ let ifilter = try InputFilter(.compress, using: algo) {(x: Int) -> Data? in
+ return f.readData(ofLength:x)
+ }
+ while let i = try ifilter.readData(ofLength: 400) {
+ payload.append(i)
+ }
+
+ // Output filter decompress
+ let g = DataSource(payload)
+ let ofilter = try OutputFilter(.decompress, using: algo) {(x: Data?) -> () in
+ if let x = x {
+ decompressed.append(x)
+ }
+ }
+ while (true) {
+ let i = g.readData(ofLength: 900)
+ try ofilter.write(i) // will finalize when i is empty
+ if i == nil { break }
+ }
+
+ print("ifilter | ofilter \(algo): \(contents.count) -> \(payload.count) -> \(decompressed.count)")
+
+ return contents == decompressed
+}
+
+func randomString(withBlockLength n: Int) -> String {
+ var strings = [String]()
+ for _ in 0 ..< n {
+ var s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
+ // Change some random chars
+ for _ in 1...10 {
+ let pos = Int.random(in: 0 ..< s.count)
+ let idx = s.index(s.startIndex, offsetBy: pos)
+ s = String(s[..<idx] + "#" + s[idx...])
+ }
+ strings.append(s)
+ }
+ return strings.joined(separator: "")
+}
+
+let tests = TestSuite("Compression")
+
+if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) {
+
+ do {
+ for blockLength in [0, 1, 2, 5, 10, 100] {
+ let testString = randomString(withBlockLength: blockLength)
+ let contents = testString.data(using: .utf8)!
+
+ for algo in Algorithm.allCases {
+ tests.test("OutputFilter/Compress/InputFilter/Decompress/\(algo)/\(blockLength)") {
+ expectDoesNotThrow({
+ expectTrue(
+ try ofiltercompress_ifilterdecompress(contents, using: algo),
+ "Failing input: \(testString)"
+ )
+ })
+ }
+
+ tests.test("InputFilter/Compress/OutputFilter/Decompress/\(algo)/\(blockLength)") {
+ expectDoesNotThrow({
+ expectTrue(
+ try ifiltercompress_ofilterdecompress(contents, using: algo),
+ "Failing input: \(testString)"
+ )
+ })
+ }
+ }
+
+ } // blockLength
+ }
+
+}
+
+runAllTests()
diff --git a/test/stdlib/ManagedBuffer.swift b/test/stdlib/ManagedBuffer.swift
index 8d39d3f..24d288c 100644
--- a/test/stdlib/ManagedBuffer.swift
+++ b/test/stdlib/ManagedBuffer.swift
@@ -40,7 +40,7 @@
struct CountAndCapacity {
var count: LifetimeTracked
- var capacity: Int
+ let capacity: Int
}
// An example of ManagedBuffer, very similar to what Array will use.
@@ -96,23 +96,6 @@
}
self.count = count + 2
}
-
- class func tryGrow(_ buffer: inout TestManagedBuffer<T>, newCapacity: Int) -> Bool {
- guard isKnownUniquelyReferenced(&buffer) else {
- return false
- }
- guard newCapacity > buffer.capacity else {
- return false
- }
-
- if tryReallocateUniquelyReferenced(buffer: &buffer,
- newMinimumCapacity: newCapacity) {
- buffer.header.capacity = newCapacity
- return true
- } else {
- return false
- }
- }
}
class MyBuffer<T> {
@@ -258,35 +241,4 @@
_fixLifetime(s2)
}
-tests.test("canGrowUsingRealloc") {
- #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
- return // realloc currently unsupported on Darwin
- #endif
- func testGrow(_ buffer: inout TestManagedBuffer<LifetimeTracked>,
- newCapacity: Int,
- shouldSucceed: Bool = true) {
- let s = TestManagedBuffer.tryGrow(&buffer, newCapacity: newCapacity)
- expectEqual(s, shouldSucceed)
- if shouldSucceed {
- expectLE(newCapacity, buffer.myCapacity)
- expectGE((newCapacity + 1) * 2, buffer.myCapacity)
- }
- repeat {
- buffer.append(LifetimeTracked(buffer.count))
- } while buffer.count < buffer.myCapacity - 2
- }
-
- var b = TestManagedBuffer<LifetimeTracked>.create(0)
- // allow some over-allocation
- expectLE(0, b.myCapacity)
- expectGE(3, b.myCapacity)
-
- testGrow(&b, newCapacity: 5)
- testGrow(&b, newCapacity: 8)
- testGrow(&b, newCapacity: 1000)
- testGrow(&b, newCapacity: 16000)
- var b2 = b
- testGrow(&b, newCapacity: 2000, shouldSucceed: false)
-}
-
runAllTests()
diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift
index fd0ae6f..06e00b0 100644
--- a/test/stmt/statements.swift
+++ b/test/stmt/statements.swift
@@ -535,6 +535,70 @@
if (x: 1) {} // expected-error {{'(x: Int)' is not convertible to 'Bool'}}
}
+// Typo correction for loop labels
+for _ in [1] {
+ break outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'}}
+}
+while true {
+ break outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'}}
+}
+repeat {
+ break outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'}}
+} while true
+
+outerLoop: for _ in [1] { // expected-note {{'outerLoop' declared here}}
+ break outerloop // expected-error {{use of unresolved label 'outerloop'; did you mean 'outerLoop'?}} {{9-18=outerLoop}}
+}
+outerLoop: for _ in [1] { // expected-note {{'outerLoop' declared here}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'; did you mean 'outerLoop'?}} {{12-21=outerLoop}}
+}
+outerLoop: while true { // expected-note {{'outerLoop' declared here}}
+ break outerloop // expected-error {{use of unresolved label 'outerloop'; did you mean 'outerLoop'?}} {{9-18=outerLoop}}
+}
+outerLoop: while true { // expected-note {{'outerLoop' declared here}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'; did you mean 'outerLoop'?}} {{12-21=outerLoop}}
+}
+outerLoop: repeat { // expected-note {{'outerLoop' declared here}}
+ break outerloop // expected-error {{use of unresolved label 'outerloop'; did you mean 'outerLoop'?}} {{9-18=outerLoop}}
+} while true
+outerLoop: repeat { // expected-note {{'outerLoop' declared here}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'; did you mean 'outerLoop'?}} {{12-21=outerLoop}}
+} while true
+
+outerLoop1: for _ in [1] { // expected-note {{did you mean 'outerLoop1'?}} {{11-20=outerLoop1}}
+ outerLoop2: for _ in [1] { // expected-note {{did you mean 'outerLoop2'?}} {{11-20=outerLoop2}}
+ break outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ }
+}
+outerLoop1: for _ in [1] { // expected-note {{did you mean 'outerLoop1'?}} {{14-23=outerLoop1}}
+ outerLoop2: for _ in [1] { // expected-note {{did you mean 'outerLoop2'?}} {{14-23=outerLoop2}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ }
+}
+outerLoop1: while true { // expected-note {{did you mean 'outerLoop1'?}} {{11-20=outerLoop1}}
+ outerLoop2: while true { // expected-note {{did you mean 'outerLoop2'?}} {{11-20=outerLoop2}}
+ break outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ }
+}
+outerLoop1: while true { // expected-note {{did you mean 'outerLoop1'?}} {{14-23=outerLoop1}}
+ outerLoop2: while true { // expected-note {{did you mean 'outerLoop2'?}} {{14-23=outerLoop2}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ }
+}
+outerLoop1: repeat { // expected-note {{did you mean 'outerLoop1'?}} {{11-20=outerLoop1}}
+ outerLoop2: repeat { // expected-note {{did you mean 'outerLoop2'?}} {{11-20=outerLoop2}}
+ break outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ } while true
+} while true
+outerLoop1: repeat { // expected-note {{did you mean 'outerLoop1'?}} {{14-23=outerLoop1}}
+ outerLoop2: repeat { // expected-note {{did you mean 'outerLoop2'?}} {{14-23=outerLoop2}}
+ continue outerloop // expected-error {{use of unresolved label 'outerloop'}}
+ } while true
+} while true
+
// Errors in case syntax
class
case, // expected-error {{expected identifier in enum 'case' declaration}} expected-error {{expected pattern}}
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 13989d7..7d64446 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -413,6 +413,7 @@
case DeclContextKind::TopLevelCodeDecl:
case DeclContextKind::AbstractFunctionDecl:
case DeclContextKind::SubscriptDecl:
+ case DeclContextKind::EnumElementDecl:
case DeclContextKind::Initializer:
case DeclContextKind::SerializedLocal:
case DeclContextKind::ExtensionDecl:
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index b151863..479c7e5 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -685,7 +685,7 @@
if (CompInv.getLangOptions().BuildSyntaxTree) {
RC<SyntaxArena> syntaxArena{new syntax::SyntaxArena()};
SynTreeCreator = std::make_shared<SyntaxTreeCreator>(
- CompInv.getMainFileSyntaxParsingCache(), syntaxArena);
+ SM, BufferID, CompInv.getMainFileSyntaxParsingCache(), syntaxArena);
}
Parser.reset(
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 53ee12b..796da09 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -1,5 +1,4 @@
add_swift_host_tool(swift
- api_notes.cpp
driver.cpp
autolink_extract_main.cpp
modulewrap_main.cpp
diff --git a/tools/driver/api_notes.cpp b/tools/driver/api_notes.cpp
deleted file mode 100644
index 57f85bb..0000000
--- a/tools/driver/api_notes.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-//===--- api_notes.cpp - Swift Compiler Frontend --------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This is the YAML to binary converter for API notes.
-///
-//===----------------------------------------------------------------------===//
-#include "clang/APINotes/APINotesYAMLCompiler.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/Triple.h"
-
-using namespace llvm;
-namespace api_notes = clang::api_notes;
-
-int apinotes_main(ArrayRef<const char *> Args) {
-
- // Mark all our options with this category, everything else (except for
- // -version and -help) will be hidden.
- static cl::OptionCategory APINotesCategory("API Notes options");
-
- static cl::opt<api_notes::ActionType>
- Action(cl::desc("Mode:"), cl::init(api_notes::ActionType::None),
- cl::values(
- clEnumValN(api_notes::ActionType::YAMLToBinary,
- "yaml-to-binary", "Convert YAML to binary format"),
- clEnumValN(api_notes::ActionType::BinaryToYAML,
- "binary-to-yaml",
- "Convert binary format to YAML"),
- clEnumValN(api_notes::ActionType::Dump,
- "dump", "Parse and dump the output")),
- cl::cat(APINotesCategory));
-
- static cl::opt<std::string>
- InputFilename(cl::Positional, cl::desc("<input file>"),
- cl::Required, cl::cat(APINotesCategory));
-
- static cl::opt<std::string>
- Target("target", cl::desc("Generate binary format for the given target"),
- cl::cat(APINotesCategory));
-
- static cl::opt<std::string>
- OutputFilename("o", cl::desc("Output file name"), cl::cat(APINotesCategory));
-
- // Hide unrelated options.
- StringMap<cl::Option *> &Options =
- cl::getRegisteredOptions(*cl::TopLevelSubCommand);
- for (auto &Option : Options) {
- if (Option.second->Category != &APINotesCategory &&
- Option.first() != "help" && Option.first() != "version") {
- Option.second->setHiddenFlag(cl::ReallyHidden);
- }
- }
-
- cl::ParseCommandLineOptions(Args.size(),
- Args.data(),
- "Swift API Notes Tool\n");
-
- if (Action == clang::api_notes::ActionType::None) {
- errs() << "action required\n";
- cl::PrintHelpMessage();
- return 1;
- }
-
- auto fileBufOrErr = MemoryBuffer::getFile(InputFilename);
- if (std::error_code EC = fileBufOrErr.getError()) {
- llvm::errs() << "\n Could not open input file: " + EC.message() << '\n';
- return true;
- }
- StringRef input = fileBufOrErr.get()->getBuffer();
-
- switch (Action) {
- case api_notes::ActionType::None:
- llvm_unreachable("handled above");
-
- case api_notes::ActionType::YAMLToBinary: {
- if (OutputFilename.empty()) {
- errs() << "output file is required\n";
- cl::PrintHelpMessage();
- return 1;
- }
-
- api_notes::OSType targetOS = api_notes::OSType::Absent;
- // TODO: Check that we've specified the target.
- if (!Target.empty()) {
- llvm::Triple target(llvm::Triple::normalize(Target));
- switch (target.getOS()) {
- case llvm::Triple::Darwin:
- case llvm::Triple::MacOSX:
- targetOS = api_notes::OSType::OSX;
- break;
- case llvm::Triple::IOS:
- targetOS = api_notes::OSType::IOS;
- break;
- case llvm::Triple::TvOS:
- targetOS = api_notes::OSType::TvOS;
- break;
- case llvm::Triple::WatchOS:
- targetOS = api_notes::OSType::WatchOS;
- break;
- default:
- errs() << "target is not supported\n";
- return 1;
- }
- }
- std::error_code EC;
- llvm::raw_fd_ostream os(OutputFilename, EC,
- llvm::sys::fs::OpenFlags::F_None);
-
- if (api_notes::compileAPINotes(input, /*sourceFile=*/nullptr, os, targetOS))
- return 1;
-
- os.flush();
-
- return os.has_error();
- }
-
- case api_notes::ActionType::BinaryToYAML: {
- if (OutputFilename.empty()) {
- errs() << "output file required\n";
- cl::PrintHelpMessage();
- return 1;
- }
-
- std::error_code EC;
- llvm::raw_fd_ostream os(OutputFilename, EC,
- llvm::sys::fs::OpenFlags::F_None);
-
- if (api_notes::decompileAPINotes(std::move(fileBufOrErr.get()), os))
- return 1;
-
- os.flush();
-
- return os.has_error();
- }
-
- case api_notes::ActionType::Dump:
- return api_notes::parseAndDumpAPINotes(input);
- }
-
- return 1;
-}
-
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index 55c5492..d8ec032 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -111,8 +111,6 @@
return true;
}
-extern int apinotes_main(ArrayRef<const char *> Args);
-
static int run_driver(StringRef ExecName,
const ArrayRef<const char *> argv) {
// Handle integrated tools.
@@ -128,10 +126,6 @@
argv.data()+argv.size()),
argv[0], (void *)(intptr_t)getExecutablePath);
}
- if (FirstArg == "-apinotes") {
- return apinotes_main(llvm::makeArrayRef(argv.data()+1,
- argv.data()+argv.size()));
- }
}
std::string Path = getExecutablePath(argv[0]);
diff --git a/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp b/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp
index 6734ace..120e69f 100644
--- a/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp
+++ b/tools/libSwiftSyntaxParser/libSwiftSyntaxParser.cpp
@@ -88,14 +88,14 @@
}
static void makeCTrivia(SmallVectorImpl<CTriviaPiece> &c_trivia,
- const Trivia &trivia) {
+ ArrayRef<ParsedTriviaPiece> trivia) {
for (const auto &piece : trivia) {
CTriviaPiece c_piece;
auto numValue =
WrapperTypeTraits<TriviaKind>::numericValue(piece.getKind());
c_piece.kind = numValue;
assert(c_piece.kind == numValue && "trivia kind value is too large");
- c_piece.length = piece.getTextLength();
+ c_piece.length = piece.getLength();
c_trivia.push_back(c_piece);
}
}
@@ -131,15 +131,15 @@
node.present = true;
}
- OpaqueSyntaxNode recordToken(const Token &tok,
- const Trivia &leadingTrivia,
- const Trivia &trailingTrivia,
+ OpaqueSyntaxNode recordToken(tok tokenKind,
+ ArrayRef<ParsedTriviaPiece> leadingTrivia,
+ ArrayRef<ParsedTriviaPiece> trailingTrivia,
CharSourceRange range) override {
SmallVector<CTriviaPiece, 8> c_leadingTrivia, c_trailingTrivia;
makeCTrivia(c_leadingTrivia, leadingTrivia);
makeCTrivia(c_trailingTrivia, trailingTrivia);
CRawSyntaxNode node;
- makeCRawToken(node, tok.getKind(), c_leadingTrivia, c_trailingTrivia,
+ makeCRawToken(node, tokenKind, c_leadingTrivia, c_trailingTrivia,
range);
return getNodeHandler()(&node);
}
@@ -187,6 +187,8 @@
LangOptions langOpts;
langOpts.BuildSyntaxTree = true;
langOpts.CollectParsedToken = false;
+ // Disable name lookups during parsing.
+ langOpts.EnableASTScopeLookup = true;
auto parseActions =
std::make_shared<CLibParseActions>(*this, SM, bufID);
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index 53121b4..c03ca90 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -3195,6 +3195,7 @@
PrintOpts = PrintOptions::printDocInterface();
} else {
PrintOpts = PrintOptions::printEverything();
+ PrintOpts.FullyQualifiedTypes = options::FullyQualifiedTypes;
PrintOpts.FullyQualifiedTypesIfAmbiguous =
options::FullyQualifiedTypesIfAmbiguous;
PrintOpts.SynthesizeSugarOnTypes = options::SynthesizeSugarOnTypes;
diff --git a/tools/swift-remoteast-test/swift-remoteast-test.cpp b/tools/swift-remoteast-test/swift-remoteast-test.cpp
index 0f3f50f..54d0029 100644
--- a/tools/swift-remoteast-test/swift-remoteast-test.cpp
+++ b/tools/swift-remoteast-test/swift-remoteast-test.cpp
@@ -42,8 +42,8 @@
// FIXME: swiftcall
/// func printType(forMetadata: Any.Type)
-LLVM_ATTRIBUTE_USED SWIFT_REMOTEAST_TEST_ABI
-extern "C" void printMetadataType(const Metadata *typeMetadata) {
+LLVM_ATTRIBUTE_USED extern "C" void SWIFT_REMOTEAST_TEST_ABI
+printMetadataType(const Metadata *typeMetadata) {
assert(Context && "context was not set");
std::shared_ptr<MemoryReader> reader(new InProcessMemoryReader());
@@ -64,8 +64,8 @@
// FIXME: swiftcall
/// func printDynamicType(_: AnyObject)
-LLVM_ATTRIBUTE_USED SWIFT_REMOTEAST_TEST_ABI
-extern "C" void printHeapMetadataType(void *object) {
+LLVM_ATTRIBUTE_USED extern "C" void SWIFT_REMOTEAST_TEST_ABI
+printHeapMetadataType(void *object) {
assert(Context && "context was not set");
std::shared_ptr<MemoryReader> reader(new InProcessMemoryReader());
@@ -127,8 +127,8 @@
// FIXME: swiftcall
/// func printTypeMemberOffset(forType: Any.Type, memberName: StaticString)
-LLVM_ATTRIBUTE_USED SWIFT_REMOTEAST_TEST_ABI
-extern "C" void printTypeMemberOffset(const Metadata *typeMetadata,
+LLVM_ATTRIBUTE_USED extern "C" void SWIFT_REMOTEAST_TEST_ABI
+printTypeMemberOffset(const Metadata *typeMetadata,
const char *memberName) {
printMemberOffset(typeMetadata, memberName, /*pass metadata*/ false);
}
@@ -136,15 +136,15 @@
// FIXME: swiftcall
/// func printTypeMetadataMemberOffset(forType: Any.Type,
/// memberName: StaticString)
-LLVM_ATTRIBUTE_USED SWIFT_REMOTEAST_TEST_ABI
-extern "C" void printTypeMetadataMemberOffset(const Metadata *typeMetadata,
- const char *memberName) {
+LLVM_ATTRIBUTE_USED extern "C" void SWIFT_REMOTEAST_TEST_ABI
+printTypeMetadataMemberOffset(const Metadata *typeMetadata,
+ const char *memberName) {
printMemberOffset(typeMetadata, memberName, /*pass metadata*/ true);
}
// FIXME: swiftcall
/// func printDynamicTypeAndAddressForExistential<T>(_: T)
-LLVM_ATTRIBUTE_USED SWIFT_REMOTEAST_TEST_ABI extern "C" void
+LLVM_ATTRIBUTE_USED extern "C" void SWIFT_REMOTEAST_TEST_ABI
printDynamicTypeAndAddressForExistential(void *object,
const Metadata *typeMetadata) {
assert(Context && "context was not set");
diff --git a/unittests/Parse/LexerTests.cpp b/unittests/Parse/LexerTests.cpp
index d694748..4233b89 100644
--- a/unittests/Parse/LexerTests.cpp
+++ b/unittests/Parse/LexerTests.cpp
@@ -4,6 +4,7 @@
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
+#include "swift/Syntax/Trivia.h"
#include "swift/Subsystems.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Process.h"
@@ -18,6 +19,7 @@
using namespace swift;
using namespace llvm;
+using syntax::TriviaKind;
// The test fixture.
class LexerTest : public ::testing::Test {
@@ -283,7 +285,7 @@
TriviaRetentionMode::WithoutTrivia);
Token Tok;
- syntax::Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -291,16 +293,16 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::eof, Tok.getKind());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
}
TEST_F(LexerTest, BOMTokenCommentNoTrivia) {
@@ -315,7 +317,7 @@
TriviaRetentionMode::WithoutTrivia);
Token Tok;
- syntax::Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::comment, Tok.getKind());
@@ -323,8 +325,8 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 3), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 3), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -332,8 +334,8 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::comment, Tok.getKind());
@@ -341,8 +343,8 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 18), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 18), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::comment, Tok.getKind());
@@ -350,16 +352,16 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 24), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 24), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::eof, Tok.getKind());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
}
TEST_F(LexerTest, BOMAttachCommentNoTrivia) {
@@ -374,7 +376,7 @@
TriviaRetentionMode::WithoutTrivia);
Token Tok;
- syntax::Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -382,16 +384,16 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 3), Tok.getCommentRange().getStart());
ASSERT_EQ(10u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::eof, Tok.getKind());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 18), Tok.getCommentRange().getStart());
ASSERT_EQ(13u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), LeadingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
}
TEST_F(LexerTest, BOMNoCommentTrivia) {
@@ -406,7 +408,7 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- syntax::Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -414,13 +416,13 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{
- syntax::TriviaPiece::garbageText("\xEF\xBB\xBF"),
- syntax::TriviaPiece::lineComment("// comment"),
- syntax::TriviaPiece::newlines(1)
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::GarbageText, strlen("\xEF\xBB\xBF")),
+ ParsedTriviaPiece(TriviaKind::LineComment, strlen("// comment")),
+ ParsedTriviaPiece(TriviaKind::Newline, 1)
}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{
- syntax::TriviaPiece::spaces(1)
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::Space, 1)
}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
@@ -428,12 +430,12 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getCommentRange().getStart());
ASSERT_EQ(0u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{
- syntax::TriviaPiece::lineComment("//xx "),
- syntax::TriviaPiece::newlines(1),
- syntax::TriviaPiece::blockComment("/* x */")
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::LineComment, strlen("//xx ")),
+ ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::BlockComment, strlen("/* x */"))
}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
}
TEST_F(LexerTest, BOMAttachCommentTrivia) {
@@ -448,7 +450,7 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- syntax::Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -456,13 +458,13 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 14), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 3), Tok.getCommentRange().getStart());
ASSERT_EQ(10u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{
- syntax::TriviaPiece::garbageText("\xEF\xBB\xBF"),
- syntax::TriviaPiece::lineComment("// comment"),
- syntax::TriviaPiece::newlines(1)
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::GarbageText, strlen("\xEF\xBB\xBF")),
+ ParsedTriviaPiece(TriviaKind::LineComment, strlen("// comment")),
+ ParsedTriviaPiece(TriviaKind::Newline, 1)
}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{
- syntax::TriviaPiece::spaces(1)
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::Space, 1)
}}), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
@@ -470,12 +472,12 @@
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 31), Tok.getLoc());
ASSERT_EQ(SourceMgr.getLocForOffset(BufferID, 18), Tok.getCommentRange().getStart());
ASSERT_EQ(13u, Tok.getCommentRange().getByteLength());
- ASSERT_EQ((syntax::Trivia{{
- syntax::TriviaPiece::lineComment("//xx "),
- syntax::TriviaPiece::newlines(1),
- syntax::TriviaPiece::blockComment("/* x */")
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::LineComment, strlen("//xx ")),
+ ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::BlockComment, strlen("/* x */"))
}}), LeadingTrivia);
- ASSERT_EQ((syntax::Trivia{{}}), TrailingTrivia);
+ ASSERT_EQ((ParsedTrivia{{}}), TrailingTrivia);
}
TEST_F(LexerTest, RestoreBasic) {
diff --git a/unittests/Parse/LexerTriviaTests.cpp b/unittests/Parse/LexerTriviaTests.cpp
index 565366d..33fcb16 100644
--- a/unittests/Parse/LexerTriviaTests.cpp
+++ b/unittests/Parse/LexerTriviaTests.cpp
@@ -1,13 +1,14 @@
#include "swift/Basic/LangOptions.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
+#include "swift/Syntax/Trivia.h"
#include "swift/Subsystems.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
using namespace swift;
-using namespace swift::syntax;
using namespace llvm;
+using syntax::TriviaKind;
class LexerTriviaTest : public ::testing::Test {};
@@ -24,22 +25,25 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ(LeadingTrivia, Trivia());
- ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
+ ASSERT_EQ(LeadingTrivia, ParsedTrivia());
+ ASSERT_EQ(TrailingTrivia,
+ (ParsedTrivia{{ParsedTriviaPiece(TriviaKind::Space, 1)}}));
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia,
- (Trivia{{TriviaPiece::newlines(1), TriviaPiece::spaces(1)}}));
- ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
+ (ParsedTrivia{{ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::Space, 1)}}));
+ ASSERT_EQ(TrailingTrivia,
+ (ParsedTrivia{{ParsedTriviaPiece(TriviaKind::Space, 1)}}));
LexerState S = L.getStateForBeginningOfToken(Tok, LeadingTrivia);
@@ -47,8 +51,10 @@
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("ccc", Tok.getText());
ASSERT_FALSE(Tok.isAtStartOfLine());
- ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::blockComment("/*C*/")}}));
- ASSERT_EQ(TrailingTrivia, Trivia());
+ ASSERT_EQ(LeadingTrivia,
+ (ParsedTrivia{{ParsedTriviaPiece(
+ TriviaKind::BlockComment, strlen("/*C*/"))}}));
+ ASSERT_EQ(TrailingTrivia, ParsedTrivia());
L.restoreState(S);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
@@ -56,8 +62,10 @@
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
ASSERT_EQ(LeadingTrivia,
- (Trivia{{TriviaPiece::newlines(1), TriviaPiece::spaces(1)}}));
- ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
+ (ParsedTrivia{{ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::Space, 1)}}));
+ ASSERT_EQ(TrailingTrivia,
+ (ParsedTrivia{{ParsedTriviaPiece(TriviaKind::Space, 1)}}));
}
TEST_F(LexerTriviaTest, TriviaHashbang) {
@@ -72,15 +80,15 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ(LeadingTrivia,
- (Trivia{{TriviaPiece::garbageText("#!/bin/swift"),
- TriviaPiece::newlines(1)}}));
+ ASSERT_EQ(LeadingTrivia, (ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::GarbageText, strlen("#!/bin/swift")),
+ ParsedTriviaPiece(TriviaKind::Newline, 1)}}));
}
TEST_F(LexerTriviaTest, TriviaHashbangAfterBOM) {
@@ -95,17 +103,17 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ(LeadingTrivia,
- (Trivia{{TriviaPiece::garbageText("\xEF\xBB\xBF"),
- TriviaPiece::garbageText("#!/bin/swift"),
- TriviaPiece::newlines(1)}}));
+ ASSERT_EQ(LeadingTrivia, (ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::GarbageText, strlen("\xEF\xBB\xBF")),
+ ParsedTriviaPiece(TriviaKind::GarbageText, strlen("#!/bin/swift")),
+ ParsedTriviaPiece(TriviaKind::Newline, 1)}}));
}
TEST_F(LexerTriviaTest, TriviaConflictMarker) {
@@ -128,7 +136,7 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -144,9 +152,10 @@
"=======\n"
"old\n"
">>>>>>> 18844bc65229786b96b89a9fc7739c0f:conflict_markers.swift";
- ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::newlines(1),
- TriviaPiece::garbageText(expectedTrivia),
- TriviaPiece::newlines(1)}}));
+ ASSERT_EQ(LeadingTrivia, (ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::GarbageText, expectedTrivia.size()),
+ ParsedTriviaPiece(TriviaKind::Newline, 1)}}));
}
TEST_F(LexerTriviaTest, TriviaCarriageReturn) {
@@ -162,27 +171,29 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ(LeadingTrivia, Trivia());
- ASSERT_EQ(TrailingTrivia, Trivia());
+ ASSERT_EQ(LeadingTrivia, ParsedTrivia());
+ ASSERT_EQ(TrailingTrivia, ParsedTrivia());
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::carriageReturns(2)}}));
- ASSERT_EQ(TrailingTrivia, Trivia());
+ ASSERT_EQ(LeadingTrivia,
+ (ParsedTrivia{{ParsedTriviaPiece(TriviaKind::CarriageReturn, 2)}}));
+ ASSERT_EQ(TrailingTrivia, ParsedTrivia());
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::eof, Tok.getKind());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::carriageReturns(1)}}));
- ASSERT_EQ(TrailingTrivia, Trivia());
+ ASSERT_EQ(LeadingTrivia,
+ (ParsedTrivia{{ParsedTriviaPiece(TriviaKind::CarriageReturn, 1)}}));
+ ASSERT_EQ(TrailingTrivia, ParsedTrivia());
}
TEST_F(LexerTriviaTest, TriviaNewLines) {
@@ -202,46 +213,46 @@
TriviaRetentionMode::WithTrivia);
Token Tok;
- Trivia LeadingTrivia, TrailingTrivia;
+ ParsedTrivia LeadingTrivia, TrailingTrivia;
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("aaa", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ((Trivia{{
- TriviaPiece::newlines(1),
- TriviaPiece::carriageReturns(1),
- TriviaPiece::carriageReturnLineFeeds(1),
- TriviaPiece::carriageReturns(2),
- TriviaPiece::carriageReturnLineFeeds(2),
- TriviaPiece::newlines(2)
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::CarriageReturn, 1),
+ ParsedTriviaPiece(TriviaKind::CarriageReturnLineFeed, 2),
+ ParsedTriviaPiece(TriviaKind::CarriageReturn, 2),
+ ParsedTriviaPiece(TriviaKind::CarriageReturnLineFeed, 4),
+ ParsedTriviaPiece(TriviaKind::Newline, 2),
}}), LeadingTrivia);
- ASSERT_EQ(Trivia(), TrailingTrivia);
+ ASSERT_EQ(ParsedTrivia(), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::identifier, Tok.getKind());
ASSERT_EQ("bbb", Tok.getText());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ((Trivia{{
- TriviaPiece::newlines(1),
- TriviaPiece::carriageReturns(1),
- TriviaPiece::carriageReturnLineFeeds(1),
- TriviaPiece::carriageReturns(2),
- TriviaPiece::carriageReturnLineFeeds(2),
- TriviaPiece::newlines(2)
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::CarriageReturn, 1),
+ ParsedTriviaPiece(TriviaKind::CarriageReturnLineFeed, 2),
+ ParsedTriviaPiece(TriviaKind::CarriageReturn, 2),
+ ParsedTriviaPiece(TriviaKind::CarriageReturnLineFeed, 4),
+ ParsedTriviaPiece(TriviaKind::Newline, 2),
}}), LeadingTrivia);
- ASSERT_EQ(Trivia(), TrailingTrivia);
+ ASSERT_EQ(ParsedTrivia(), TrailingTrivia);
L.lex(Tok, LeadingTrivia, TrailingTrivia);
ASSERT_EQ(tok::eof, Tok.getKind());
ASSERT_TRUE(Tok.isAtStartOfLine());
- ASSERT_EQ((Trivia{{
- TriviaPiece::newlines(1),
- TriviaPiece::carriageReturns(1),
- TriviaPiece::carriageReturnLineFeeds(1),
- TriviaPiece::carriageReturns(2),
- TriviaPiece::carriageReturnLineFeeds(2),
- TriviaPiece::newlines(2)
+ ASSERT_EQ((ParsedTrivia{{
+ ParsedTriviaPiece(TriviaKind::Newline, 1),
+ ParsedTriviaPiece(TriviaKind::CarriageReturn, 1),
+ ParsedTriviaPiece(TriviaKind::CarriageReturnLineFeed, 2),
+ ParsedTriviaPiece(TriviaKind::CarriageReturn, 2),
+ ParsedTriviaPiece(TriviaKind::CarriageReturnLineFeed, 4),
+ ParsedTriviaPiece(TriviaKind::Newline, 2),
}}), LeadingTrivia);
- ASSERT_EQ(Trivia(), TrailingTrivia);
+ ASSERT_EQ(ParsedTrivia(), TrailingTrivia);
}
diff --git a/utils/bug_reducer/tests/test_funcbugreducer.py b/utils/bug_reducer/tests/test_funcbugreducer.py
index 4363f7d..b917a6d 100644
--- a/utils/bug_reducer/tests/test_funcbugreducer.py
+++ b/utils/bug_reducer/tests/test_funcbugreducer.py
@@ -120,11 +120,11 @@
output_file_re = re.compile(r'\*\*\* Final File: .*' + re_end)
output_matches = [
1 for o in output if output_file_re.match(o) is not None]
- self.assertEquals(sum(output_matches), 1)
+ self.assertEqual(sum(output_matches), 1)
# Make sure our final output command does not have -emit-sib in
# the output. We want users to get sil output when they type in
# the relevant command.
- self.assertEquals([], [o for o in output if '-emit-sib' in o])
+ self.assertEqual([], [o for o in output if '-emit-sib' in o])
if __name__ == '__main__':
diff --git a/utils/bug_reducer/tests/test_optbugreducer.py b/utils/bug_reducer/tests/test_optbugreducer.py
index 48479ba..5ef9a33 100644
--- a/utils/bug_reducer/tests/test_optbugreducer.py
+++ b/utils/bug_reducer/tests/test_optbugreducer.py
@@ -108,11 +108,11 @@
output_file_re = re.compile(r'\*\*\* Final File: .*' + re_end)
output_matches = [
1 for o in output if output_file_re.match(o) is not None]
- self.assertEquals(sum(output_matches), 1)
+ self.assertEqual(sum(output_matches), 1)
# Make sure our final output command does not have -emit-sib in
# the output. We want users to get sil output when they type in
# the relevant command.
- self.assertEquals([], [o for o in output if '-emit-sib' in o])
+ self.assertEqual([], [o for o in output if '-emit-sib' in o])
def test_suffix_in_need_of_prefix(self):
name = 'testsuffixinneedofprefix'
@@ -137,11 +137,11 @@
output_file_re = re.compile(r'\*\*\* Final File: .*' + re_end)
output_matches = [
1 for o in output if output_file_re.match(o) is not None]
- self.assertEquals(sum(output_matches), 1)
+ self.assertEqual(sum(output_matches), 1)
# Make sure our final output command does not have -emit-sib in the
# output. We want users to get sil output when they type in the
# relevant command.
- self.assertEquals([], [o for o in output if '-emit-sib' in o])
+ self.assertEqual([], [o for o in output if '-emit-sib' in o])
def test_reduce_function(self):
name = 'testreducefunction'
@@ -170,11 +170,11 @@
output_file_re = re.compile(r'\*\*\* Final File: .*' + re_end)
output_matches = [
1 for o in output if output_file_re.match(o) is not None]
- self.assertEquals(sum(output_matches), 1)
+ self.assertEqual(sum(output_matches), 1)
# Make sure our final output command does not have -emit-sib in the
# output. We want users to get sil output when they type in the
# relevant command.
- self.assertEquals([], [o for o in output if '-emit-sib' in o])
+ self.assertEqual([], [o for o in output if '-emit-sib' in o])
if __name__ == '__main__':
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index 440cfb2..c5e093a 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -1772,3 +1772,9 @@
swift-include-tests=0
darwin-deployment-version-ios=10.0
darwin-crash-reporter-client=1
+
+[preset: build_swiftsyntax_release]
+release
+no-assertions
+build-libparser-only
+swiftsyntax
diff --git a/utils/build-script b/utils/build-script
index b87da65..5b58f38 100755
--- a/utils/build-script
+++ b/utils/build-script
@@ -404,6 +404,7 @@
if not args.test_watchos_host:
self.platforms_to_skip_test_host.add(
StdlibDeploymentTarget.AppleWatch)
+ self.build_libparser_only = args.build_libparser_only
def initialize_runtime_environment(self):
"""Change the program environment for building."""
@@ -697,7 +698,8 @@
impl_args += ["--skip-test-optimized"]
if not args.test_optimize_for_size:
impl_args += ["--skip-test-optimize-for-size"]
-
+ if args.build_libparser_only:
+ impl_args += ["--build-libparser-only"]
if args.android:
impl_args += [
"--android-arch", args.android_arch,
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 6357370..7411576 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -103,6 +103,7 @@
installable-package "" "the path to the archive of the installation directory"
test-installable-package "" "whether to run post-packaging tests on the produced package"
reconfigure "" "force a CMake configuration run even if CMakeCache.txt already exists"
+ build-libparser-only "" "only build libSwiftSyntaxParser"
skip-reconfigure "" "set to skip reconfigure"
swift-primary-variant-sdk "" "default SDK for target binaries"
swift-primary-variant-arch "" "default arch for target binaries"
@@ -1140,7 +1141,6 @@
# and architecture of each stdlib target -- currently it only captures the SDK.
#
# We turn these targets in to SWIFT_SDKS in `calculate_targets_for_host()`
-
if [[ $(is_cross_tools_host $1) ]] ; then
echo "$1"
else
@@ -1824,6 +1824,16 @@
SWIFT_TEST="$(build_directory_bin ${LOCAL_HOST} swiftpm)/swift-test"
fi
+ if [ "${BUILD_LIBPARSER_ONLY}" ]; then
+ # we don't have a compiler built so we have to use the one in the environment.
+ SWIFTC_BIN="$(xcrun_find_tool swiftc)"
+ # we don't have a swiftpm built so we have to use the one in the environment.
+ SWIFT_BUILD="$(xcrun_find_tool swift-build)"
+ SWIFT_TEST="$(xcrun_find_tool swift-test)"
+ else
+ SWIFTC_BIN="$(build_directory_bin ${LOCAL_HOST} swift)/swiftc"
+ fi
+
swiftsyntax_build_command=("${SWIFTSYNTAX_SOURCE_DIR}/build-script.py")
# Add --release if we have to build in release mode.
if [[ $(is_cmake_release_build_type "${SWIFTSYNTAX_BUILD_TYPE}") ]] ; then
@@ -1836,7 +1846,7 @@
--build-dir="${build_dir}"
--swift-build-exec="${SWIFT_BUILD}"
--swift-test-exec="${SWIFT_TEST}"
- --swiftc-exec="$(build_directory_bin ${LOCAL_HOST} swift)/swiftc"
+ --swiftc-exec="${SWIFTC_BIN}"
--syntax-parser-header-dir="${SWIFT_SOURCE_DIR}/include/swift-c/SyntaxParser"
--syntax-parser-lib-dir="$(build_directory ${host} swift)/lib"
--swift-syntax-test-exec="$(build_directory_bin ${LOCAL_HOST} swift)/swift-syntax-test"
@@ -2292,7 +2302,6 @@
-DSWIFT_BUILD_EXTERNAL_PERF_TESTSUITE:BOOL=$(true_false "${build_external_perf_testsuite_this_time}")
-DSWIFT_BUILD_EXAMPLES:BOOL=$(true_false "${BUILD_SWIFT_EXAMPLES}")
-DSWIFT_INCLUDE_TESTS:BOOL=$(true_false "${build_tests_this_time}")
- -DSWIFT_INSTALL_COMPONENTS:STRING="${SWIFT_INSTALL_COMPONENTS}"
-DSWIFT_EMBED_BITCODE_SECTION:BOOL=$(true_false "${EMBED_BITCODE_SECTION}")
-DSWIFT_TOOLS_ENABLE_LTO:STRING="${SWIFT_TOOLS_ENABLE_LTO}"
-DSWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER:BOOL=$(true_false "${BUILD_RUNTIME_WITH_HOST_COMPILER}")
@@ -2363,6 +2372,13 @@
)
fi
+ if [ "${SWIFT_INSTALL_COMPONENTS}" ] ; then
+ cmake_options=(
+ "${cmake_options[@]}"
+ -DSWIFT_INSTALL_COMPONENTS:STRING="${SWIFT_INSTALL_COMPONENTS}"
+ )
+ fi
+
if contains_product "lldb" ; then
lldb_build_dir=$(build_directory ${host} lldb)
cmake_options=(
@@ -2382,7 +2398,9 @@
build_targets=("${build_targets[@]}"
"${SWIFT_BENCHMARK_TARGETS[@]}")
fi
-
+ if [ "${BUILD_LIBPARSER_ONLY}" ]; then
+ build_targets=(libSwiftSyntaxParser)
+ fi
skip_build=${SKIP_BUILD_SWIFT}
;;
lldb)
@@ -3154,7 +3172,7 @@
"${lldb_build_dir}/lit" \
${LLVM_LIT_ARGS} \
--xunit-xml-output=${results_dir}/results.xml \
- --param dotest-args="--build-dir ${lldb_build_dir}/lldb-test-build.noindex ${LLDB_TEST_SUBDIR_CLAUSE} ${LLDB_TEST_CATEGORIES} -G swift-history --swift-compiler \"${LLDB_TEST_SWIFT_COMPATIBILITY}\" -t -E \"${DOTEST_EXTRA}\""
+ --param dotest-args="--build-dir ${lldb_build_dir}/lldb-test-build.noindex ${LLDB_TEST_SUBDIR_CLAUSE} ${LLDB_TEST_CATEGORIES} -G swift-history --swift-compiler \"${LLDB_TEST_SWIFT_COMPATIBILITY}\" -t -E \"${DOTEST_EXTRA}\"" --filter=compat
fi
else
with_pushd "${results_dir}" \
diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py
index e6618b9..5a399e2 100644
--- a/utils/build_swift/driver_arguments.py
+++ b/utils/build_swift/driver_arguments.py
@@ -542,6 +542,9 @@
option('--build-ninja', toggle_true,
help='build the Ninja tool')
+ option(['--build-libparser-only'], store_true('build_libparser_only'),
+ help='build only libParser for SwiftSyntax')
+
# -------------------------------------------------------------------------
in_group('Extra actions to perform before or in addition to building')
diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py
index 4dcf045..a61d466 100644
--- a/utils/build_swift/tests/expected_options.py
+++ b/utils/build_swift/tests/expected_options.py
@@ -82,6 +82,7 @@
'build_swift_stdlib_unittest_extra': False,
'build_swiftpm': False,
'build_swiftsyntax': False,
+ 'build_libparser_only': False,
'build_skstresstester': False,
'build_swiftevolve': False,
'build_tvos': True,
@@ -400,6 +401,7 @@
SetTrueOption('--skip-build'),
SetTrueOption('--swiftpm', dest='build_swiftpm'),
SetTrueOption('--swiftsyntax', dest='build_swiftsyntax'),
+ SetTrueOption('--build-libparser-only', dest='build_libparser_only'),
SetTrueOption('--skstresstester', dest='build_skstresstester'),
SetTrueOption('--swiftevolve', dest='build_swiftevolve'),
SetTrueOption('-B', dest='benchmark'),
diff --git a/utils/build_swift/tests/test_driver_arguments.py b/utils/build_swift/tests/test_driver_arguments.py
index 2f2bd52..974631f 100644
--- a/utils/build_swift/tests/test_driver_arguments.py
+++ b/utils/build_swift/tests/test_driver_arguments.py
@@ -561,14 +561,14 @@
with self.assertNotRaises(ParserError):
namespace = self.parse_default_args(['--debug'])
- self.assertEquals(namespace.cmark_build_variant, 'Debug')
- self.assertEquals(namespace.foundation_build_variant, 'Debug')
- self.assertEquals(namespace.libdispatch_build_variant, 'Debug')
- self.assertEquals(namespace.libicu_build_variant, 'Debug')
- self.assertEquals(namespace.lldb_build_variant, 'Debug')
- self.assertEquals(namespace.llvm_build_variant, 'Debug')
- self.assertEquals(namespace.swift_build_variant, 'Debug')
- self.assertEquals(namespace.swift_stdlib_build_variant, 'Debug')
+ self.assertEqual(namespace.cmark_build_variant, 'Debug')
+ self.assertEqual(namespace.foundation_build_variant, 'Debug')
+ self.assertEqual(namespace.libdispatch_build_variant, 'Debug')
+ self.assertEqual(namespace.libicu_build_variant, 'Debug')
+ self.assertEqual(namespace.lldb_build_variant, 'Debug')
+ self.assertEqual(namespace.llvm_build_variant, 'Debug')
+ self.assertEqual(namespace.swift_build_variant, 'Debug')
+ self.assertEqual(namespace.swift_stdlib_build_variant, 'Debug')
def test_implied_defaults_skip_build(self):
with self.assertNotRaises(ParserError):
@@ -690,6 +690,12 @@
self.assertFalse(namespace.test_tvos_host)
self.assertFalse(namespace.test_watchos_host)
self.assertFalse(namespace.test_android_host)
+ self.assertFalse(namespace.build_libparser_only)
+
+ def test_build_lib_swiftsyntaxparser_only(self):
+ with self.assertNotRaises(ParserError):
+ namespace = self.parse_default_args(['--build-libparser-only'])
+ self.assertTrue(namespace.build_libparser_only)
if __name__ == '__main__':
diff --git a/utils/find-overlay-deps-closure.sh b/utils/find-overlay-deps-closure.sh
index 4d024ad..3b11a23 100755
--- a/utils/find-overlay-deps-closure.sh
+++ b/utils/find-overlay-deps-closure.sh
@@ -15,7 +15,7 @@
set -o pipefail
set -e
-OVERLAY_NAME_ALTERNATION="AppKit|AssetsLibrary|AVFoundation|CallKit|CloudKit|Contacts|CoreAudio|CoreData|CoreGraphics|CoreImage|CoreLocation|CoreMedia|CryptoTokenKit|dispatch|Foundation|GameplayKit|GLKit|HomeKit|IOKit|Intents|MapKit|objc|OpenCL|os|Photos|QuartzCore|SafariServices|SceneKit|simd|SpriteKit|UIKit|WatchKit|XCTest|xpc"
+OVERLAY_NAME_ALTERNATION="AppKit|AssetsLibrary|AVFoundation|CallKit|CloudKit|Compression|Contacts|CoreAudio|CoreData|CoreGraphics|CoreImage|CoreLocation|CoreMedia|CryptoTokenKit|dispatch|Foundation|GameplayKit|GLKit|HomeKit|IOKit|Intents|MapKit|objc|OpenCL|os|Photos|QuartzCore|SafariServices|SceneKit|simd|SpriteKit|UIKit|WatchKit|XCTest|xpc"
function find_deps() {
local OVERLAY_ARG=$1
@@ -39,7 +39,7 @@
exit 123
fi
- local REGEX="./Frameworks/(${OVERLAY_NAME_ALTERNATION}).framework/.*|.*/usr/include/(xpc|dispatch|os|objc|simd)/.*\.h"
+ local REGEX="./Frameworks/(${OVERLAY_NAME_ALTERNATION}).framework/.*|.*/usr/include/(xpc|dispatch|os|objc|simd|compression)/.*\.h"
# shellcheck disable=SC1004
IFS='\
diff --git a/utils/gyb.py b/utils/gyb.py
index 5f44e18..d9ce0e7 100755
--- a/utils/gyb.py
+++ b/utils/gyb.py
@@ -751,7 +751,7 @@
def expand(filename, line_directive=_default_line_directive, **local_bindings):
- r"""Return the contents of the givepn template file, executed with the given
+ r"""Return the contents of the given template file, executed with the given
local bindings.
>>> from tempfile import NamedTemporaryFile
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index 9157436..57e7422 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -210,15 +210,6 @@
Child('RightSquare', kind='RightSquareBracketToken'),
]),
- # .foo
- Node('ImplicitMemberExpr', kind='Expr',
- children=[
- Child("Dot", kind='PrefixPeriodToken'),
- Child("Name", kind='Token'),
- Child('DeclNameArguments', kind='DeclNameArguments',
- is_optional=True),
- ]),
-
# function-call-argument -> label? ':'? expression ','?
Node('FunctionCallArgument', kind='Syntax',
traits=['WithTrailingComma'],
@@ -297,27 +288,20 @@
Child("SecondChoice", kind='Expr')
]),
- # a.b
+ # expr?.name
Node('MemberAccessExpr', kind='Expr',
children=[
# The base needs to be optional to parse expressions in key paths
# like \.a
Child("Base", kind='Expr', is_optional=True),
- Child("Dot", kind='PeriodToken'),
- Child("Name", kind='Token'),
- Child('DeclNameArguments', kind='DeclNameArguments',
- is_optional=True),
- ]),
-
- # dot-self-expr -> expr '.' 'self'
- Node('DotSelfExpr', kind='Expr',
- children=[
- Child('Expression', kind='Expr'),
- Child('Dot', kind='Token',
+ Child("Dot", kind='Token',
token_choices=[
'PeriodToken', 'PrefixPeriodToken'
]),
- Child('SelfKeyword', kind='SelfToken'),
+ # Name could be 'self'
+ Child("Name", kind='Token'),
+ Child('DeclNameArguments', kind='DeclNameArguments',
+ is_optional=True),
]),
# is TypeName
diff --git a/utils/round-trip-syntax-test b/utils/round-trip-syntax-test
index 29eefe3..87cf2f7 100755
--- a/utils/round-trip-syntax-test
+++ b/utils/round-trip-syntax-test
@@ -3,6 +3,7 @@
from __future__ import print_function, unicode_literals
import argparse
+import difflib
import logging
import os
import subprocess
@@ -36,62 +37,52 @@
return [self.swift_syntax_test, self.action,
'-input-source-filename', self.input_filename]
- @property
- def diff_command(self):
- return ['/usr/bin/diff', '-u', self.input_filename, '-']
-
- def diff(self):
- logging.debug(' '.join(self.diff_command))
- diff = subprocess.Popen(self.diff_command, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- stdout, stderr = diff.communicate(self.stdout)
- if diff.returncode != 0:
- return stdout
- assert stdout == ''
- assert stderr == ''
- return None
-
def run(self):
command = self.test_command
logging.debug(' '.join(command))
- self.output_file = tempfile.NamedTemporaryFile('w')
- self.stderr_file = tempfile.NamedTemporaryFile('w')
+ self.output_file = tempfile.NamedTemporaryFile('w', delete=False)
+ self.stderr_file = tempfile.NamedTemporaryFile('w', delete=False)
process = subprocess.Popen(command, stdout=self.output_file,
stderr=self.stderr_file)
process.wait()
self.returncode = process.returncode
+ self.output_file.close()
+ self.stderr_file.close()
+
with open(self.output_file.name, 'r') as stdout_in:
self.stdout = stdout_in.read()
with open(self.stderr_file.name, 'r') as stderr_in:
self.stderr = stderr_in.read()
- self.output_file.flush()
- self.stderr_file.flush()
+ os.remove(self.output_file.name)
+ os.remove(self.stderr_file.name)
- try:
- if self.returncode != 0:
- if self.skip_bad_syntax:
- logging.warning('---===WARNING===--- Lex/parse had error'
- ' diagnostics, so not diffing. Skipping'
- ' this file due to -skip-bad-syntax.')
- logging.error(' '.join(command))
- return None
- else:
- logging.error('---===ERROR===--- Lex/parse had error'
- ' diagnostics, so not diffing.')
- logging.error(' '.join(command))
- logging.error(self.stdout)
- logging.error(self.stderr)
- raise RuntimeError()
- finally:
- self.output_file.close()
- self.stderr_file.close()
+ if self.returncode != 0:
+ if self.skip_bad_syntax:
+ logging.warning('---===WARNING===--- Lex/parse had error'
+ ' diagnostics, so not diffing. Skipping'
+ ' this file due to -skip-bad-syntax.')
+ logging.error(' '.join(command))
+ return None
+ else:
+ logging.error('---===ERROR===--- Lex/parse had error'
+ ' diagnostics, so not diffing.')
+ logging.error(' '.join(command))
+ logging.error(self.stdout)
+ logging.error(self.stderr)
+ raise RuntimeError()
- diff = self.diff()
- return diff
+ contents = ''.join(map(lambda l: l.decode('utf-8', errors='replace'),
+ open(self.input_filename).readlines()))
+ lines = difflib.unified_diff(contents,
+ self.stdout.decode('utf-8',
+ errors='replace'),
+ fromfile=self.input_filename,
+ tofile='-')
+ diff = '\n'.join(line for line in lines)
+ return diff if diff else None
def swift_files_in_dir(d):
diff --git a/utils/rusage.py b/utils/rusage.py
index 2701a70..e0195ac 100755
--- a/utils/rusage.py
+++ b/utils/rusage.py
@@ -36,6 +36,7 @@
import resource
import subprocess
import sys
+import time
class MemAction(argparse.Action):
@@ -79,6 +80,9 @@
metavar="T",
help="time (in secs, or ..'ms', 'us')",
action=TimeAction)
+parser.add_argument("--wall-time",
+ help="wall time (in secs, or ..'ms', 'us')",
+ action='store_true')
parser.add_argument("--enforce",
action='store_true',
default=False,
@@ -125,7 +129,13 @@
sys.stderr.write("rusage: setrlimit(RLIMIT_RSS, %d)\n"
% mem)
resource.setrlimit(resource.RLIMIT_RSS, (mem, mem))
+
+start = time.time()
ret = subprocess.call(args.remainder)
+end = time.time()
+
+wall_time = end - start
+
used = resource.getrusage(resource.RUSAGE_CHILDREN)
if args.verbose:
@@ -144,18 +154,27 @@
if args.verbose or over_time:
sys.stderr.write("rusage: subprocess time: %.6f secs\n"
% used.ru_utime)
+ if args.wall_time:
+ sys.stderr.write("rusage: subprocess wall time: %.6f secs\n"
+ % wall_time)
if over_time:
sys.stderr.write("rusage: exceeded limit: %.6f secs\n"
% args.time)
if args.csv:
fieldnames = ["time", "mem", "run"]
+ row = {
+ 'time': used.ru_utime,
+ 'mem': used.ru_maxrss,
+ 'run': args.csv_name
+ }
+ if args.wall_time:
+ row['wall'] = wall_time
+ fieldnames.insert(1, 'wall')
out = csv.DictWriter(args.csv_output, fieldnames, dialect='excel-tab')
if args.csv_header:
out.writeheader()
- out.writerow(dict(time=used.ru_utime,
- mem=used.ru_maxrss,
- run=args.csv_name))
+ out.writerow(row)
if over_mem or over_time:
sys.exit(-1)
diff --git a/validation-test/Runtime/Inputs/class-layout-from-objc/Classes.swift b/validation-test/Runtime/Inputs/class-layout-from-objc/Classes.swift
new file mode 100644
index 0000000..7c45961
--- /dev/null
+++ b/validation-test/Runtime/Inputs/class-layout-from-objc/Classes.swift
@@ -0,0 +1,65 @@
+import Resilient
+import Foundation
+import OneWordSuperclass
+
+public class StaticClass: OneWordSuperclass {
+ @objc var first: Int32 = 0
+ var middle = GrowsToInt64()
+ @objc var last: Int = 0
+
+ @objc public static var offsetOfFirst: Int {
+ // IRGen lays out Swift classes that subclass Objective-C classes as if the
+ // only superclass was NSObject, so the starting (offset % alignment) isn't
+ // always 0. This means that on 32-bit platforms we'll have a gap *before*
+ // 'first' when we need 8-byte alignment, rather than after as you'd see in
+ // a struct (or base class).
+ return max(MemoryLayout<Int>.size, MemoryLayout<GrowsToInt64>.alignment) +
+ MemoryLayout<Int>.size
+ }
+
+ @objc public static var totalSize: Int {
+ return (2 * MemoryLayout<Int>.size) +
+ (2 * MemoryLayout<GrowsToInt64>.size) + // alignment
+ MemoryLayout<Int>.size
+ }
+}
+
+/// This class has the same layout as `StaticClass`, but will be accessed using
+/// `NSClassFromString` instead of `+class`.
+public class DynamicClass: OneWordSuperclass {
+ @objc var first: Int32 = 0
+ var middle = GrowsToInt64()
+ @objc var last: Int = 0
+
+ @objc public static var offsetOfFirst: Int {
+ // See above.
+ return max(MemoryLayout<Int>.size, MemoryLayout<GrowsToInt64>.alignment) +
+ MemoryLayout<Int>.size
+ }
+
+ @objc public static var totalSize: Int {
+ return (2 * MemoryLayout<Int>.size) +
+ (2 * MemoryLayout<GrowsToInt64>.size) + // alignment
+ MemoryLayout<Int>.size
+ }
+}
+
+public class PureSwiftBaseClass {
+ var word: Int64 = 0
+}
+
+public class PureSwiftClass: PureSwiftBaseClass {
+ @objc var first: Int32 = 0
+ var middle = GrowsToInt64()
+ @objc var last: Int = 0
+
+ @objc public static var offsetOfFirst: Int {
+ return (2 * MemoryLayout<Int>.size) + MemoryLayout<Int64>.size
+ }
+
+ @objc public static var totalSize: Int {
+ return (2 * MemoryLayout<Int>.size) + MemoryLayout<Int64>.size +
+ (2 * MemoryLayout<GrowsToInt64>.size) + // alignment
+ MemoryLayout<Int>.size
+ }
+}
diff --git a/validation-test/Runtime/Inputs/class-layout-from-objc/OneWordSuperclass.h b/validation-test/Runtime/Inputs/class-layout-from-objc/OneWordSuperclass.h
new file mode 100644
index 0000000..8abbec0
--- /dev/null
+++ b/validation-test/Runtime/Inputs/class-layout-from-objc/OneWordSuperclass.h
@@ -0,0 +1,4 @@
+@import Foundation;
+
+@interface OneWordSuperclass : NSObject
+@end
diff --git a/validation-test/Runtime/Inputs/class-layout-from-objc/OneWordSuperclass.m b/validation-test/Runtime/Inputs/class-layout-from-objc/OneWordSuperclass.m
new file mode 100644
index 0000000..42d7614
--- /dev/null
+++ b/validation-test/Runtime/Inputs/class-layout-from-objc/OneWordSuperclass.m
@@ -0,0 +1,6 @@
+#import "OneWordSuperclass.h"
+
+@implementation OneWordSuperclass {
+ intptr_t unused;
+}
+@end
diff --git a/validation-test/Runtime/Inputs/class-layout-from-objc/Resilient.swift b/validation-test/Runtime/Inputs/class-layout-from-objc/Resilient.swift
new file mode 100644
index 0000000..a9f4b6e
--- /dev/null
+++ b/validation-test/Runtime/Inputs/class-layout-from-objc/Resilient.swift
@@ -0,0 +1,11 @@
+public struct GrowsToInt64 {
+ #if SMALL
+ var value: Int32
+ #elseif BIG
+ var value: Int64
+ #else
+ #error("Must define SMALL or BIG")
+ #endif
+
+ public init() { self.value = 0 }
+}
diff --git a/validation-test/Runtime/Inputs/class-layout-from-objc/module.modulemap b/validation-test/Runtime/Inputs/class-layout-from-objc/module.modulemap
new file mode 100644
index 0000000..76fb327
--- /dev/null
+++ b/validation-test/Runtime/Inputs/class-layout-from-objc/module.modulemap
@@ -0,0 +1,4 @@
+module OneWordSuperclass {
+ header "OneWordSuperclass.h"
+ export *
+}
diff --git a/validation-test/Runtime/class-layout-from-objc.m b/validation-test/Runtime/class-layout-from-objc.m
new file mode 100644
index 0000000..47cbee4
--- /dev/null
+++ b/validation-test/Runtime/class-layout-from-objc.m
@@ -0,0 +1,78 @@
+// Check that when Objective-C is first to touch a Swift class, it gives the
+// Swift runtime a chance to update instance size and ivar offset metadata.
+
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -emit-library -emit-module -o %t/libResilient.dylib %S/Inputs/class-layout-from-objc/Resilient.swift -Xlinker -install_name -Xlinker @executable_path/libResilient.dylib -Xfrontend -enable-resilience -DSMALL
+
+// RUN: %target-clang -c %S/Inputs/class-layout-from-objc/OneWordSuperclass.m -fmodules -fobjc-arc -o %t/OneWordSuperclass.o
+// RUN: %target-build-swift -emit-library -o %t/libClasses.dylib -emit-objc-header-path %t/Classes.h -I %t -I %S/Inputs/class-layout-from-objc/ %S/Inputs/class-layout-from-objc/Classes.swift %t/OneWordSuperclass.o -Xlinker -install_name -Xlinker @executable_path/libClasses.dylib -lResilient -L %t
+// RUN: %target-clang %s -I %S/Inputs/class-layout-from-objc/ -I %t -fmodules -fobjc-arc -o %t/main -lResilient -lClasses -L %t
+// RUN: %target-codesign %t/main %t/libResilient.dylib %t/libClasses.dylib
+// RUN: %target-run %t/main OLD %t/libResilient.dylib %t/libClasses.dylib
+
+// RUN: %target-build-swift -emit-library -emit-module -o %t/libResilient.dylib %S/Inputs/class-layout-from-objc/Resilient.swift -Xlinker -install_name -Xlinker @executable_path/libResilient.dylib -Xfrontend -enable-resilience -DBIG
+// RUN: %target-codesign %t/libResilient.dylib
+// RUN: %target-run %t/main NEW %t/libResilient.dylib %t/libClasses.dylib
+
+// Try again when the class itself is also resilient.
+// RUN: %target-build-swift -emit-library -o %t/libClasses.dylib -emit-objc-header-path %t/Classes.h -I %S/Inputs/class-layout-from-objc/ -I %t %S/Inputs/class-layout-from-objc/Classes.swift %t/OneWordSuperclass.o -Xlinker -install_name -Xlinker @executable_path/libClasses.dylib -lResilient -L %t
+// RUN: %target-codesign %t/libClasses.dylib
+// RUN: %target-run %t/main OLD %t/libResilient.dylib %t/libClasses.dylib
+
+// RUN: %target-build-swift -emit-library -emit-module -o %t/libResilient.dylib %S/Inputs/class-layout-from-objc/Resilient.swift -Xlinker -install_name -Xlinker @executable_path/libResilient.dylib -Xfrontend -enable-resilience -DSMALL
+// RUN: %target-codesign %t/libResilient.dylib
+// RUN: %target-run %t/main NEW %t/libResilient.dylib %t/libClasses.dylib
+
+// REQUIRES: executable_test
+// REQUIRES: objc_interop
+
+#import <objc/runtime.h>
+#import <assert.h>
+#import <dlfcn.h>
+#import <stdbool.h>
+#import <string.h>
+
+#import "Classes.h"
+
+void checkClass(Class c) {
+ assert(c);
+
+ size_t expectedSize = [c totalSize];
+ size_t actualSize = class_getInstanceSize([c class]);
+ NSLog(@"%@: expected size %zd, actual size %zd", c, expectedSize, actualSize);
+ assert(expectedSize == actualSize);
+
+ size_t expectedOffsetOfFirst = [c offsetOfFirst];
+ size_t offsetOfFirst = ivar_getOffset(class_getInstanceVariable(c, "first"));
+ NSLog(@"expected offset of 'first' %zd, actual %zd",
+ expectedOffsetOfFirst, offsetOfFirst);
+ assert(offsetOfFirst == expectedOffsetOfFirst);
+
+ size_t offsetOfLast = ivar_getOffset(class_getInstanceVariable(c, "last"));
+ NSLog(@"offset of 'last' %zd", offsetOfLast);
+ assert(offsetOfLast == actualSize - sizeof(intptr_t));
+}
+
+int main(int argc, const char * const argv[]) {
+ assert(argc > 1);
+
+ if (!strcmp(argv[1], "OLD")) {
+ ;
+ } else if (!strcmp(argv[1], "NEW")) {
+ // Only test the new behavior on a new enough libobjc.
+ if (!dlsym(RTLD_NEXT, "_objc_realizeClassFromSwift")) {
+ fprintf(stderr, "skipping evolution tests; OS too old\n");
+ return EXIT_SUCCESS;
+ }
+ } else {
+ fprintf(stderr, "usage: %s (OLD|NEW)\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ @autoreleasepool {
+ NSLog(@"%zd", class_getInstanceSize([OneWordSuperclass class]));
+ checkClass([StaticClass class]);
+ checkClass(objc_getClass("Classes.DynamicClass"));
+ checkClass(objc_getClass("Classes.PureSwiftClass"));
+ }
+}
diff --git a/validation-test/Sanitizers/witness_table_lookup.swift b/validation-test/Sanitizers/witness_table_lookup.swift
index f3a9313..33994d1 100644
--- a/validation-test/Sanitizers/witness_table_lookup.swift
+++ b/validation-test/Sanitizers/witness_table_lookup.swift
@@ -3,6 +3,7 @@
// REQUIRES: executable_test
// REQUIRES: stress_test
// REQUIRES: tsan_runtime
+// UNSUPPORTED: CPU=powerpc64le
// Check that TSan does not report spurious races in witness table lookup.
diff --git a/validation-test/Sema/type_checker_crashers_fixed/rdar47266563.swift b/validation-test/Sema/type_checker_crashers_fixed/rdar47266563.swift
new file mode 100644
index 0000000..f23f296
--- /dev/null
+++ b/validation-test/Sema/type_checker_crashers_fixed/rdar47266563.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-frontend %s -typecheck
+
+print(true ? "readline" : nil)
diff --git a/validation-test/compiler_scale/function_bodies.gyb b/validation-test/compiler_scale/function_bodies.gyb
index 49cfe39..38b7782 100644
--- a/validation-test/compiler_scale/function_bodies.gyb
+++ b/validation-test/compiler_scale/function_bodies.gyb
@@ -3,3 +3,35 @@
// REQUIRES: asserts
func method${N}() {}
+
+class C${N} {
+ func method${N}() {}
+}
+
+extension C${N} {
+ func otherMethod${N}() {}
+}
+
+struct S${N} {
+ func method${N}() {}
+}
+
+extension S${N} {
+ func otherMethod${N}() {}
+}
+
+enum E${N} {
+ func method${N}() {}
+}
+
+extension E${N} {
+ func otherMethod${N}() {}
+}
+
+protocol P${N} {
+ func method${N}()
+}
+
+extension P${N} {
+ func otherMethod${N}() {}
+}
\ No newline at end of file
diff --git a/validation-test/execution/arc_36509461.swift b/validation-test/execution/arc_36509461.swift
index 56f4603..5c730e3 100644
--- a/validation-test/execution/arc_36509461.swift
+++ b/validation-test/execution/arc_36509461.swift
@@ -9,6 +9,9 @@
// REQUIRES: objc_interop
// REQUIRES: OS=macosx
+// rdar://problem/47367694 tracks re-enabling this test for backward deployment.
+// UNSUPPORTED: remote_run
+
import Foundation
struct FakeUUID {