git @ Cat's Eye Technologies SixtyPical / 3d88226
Implement --prune-unreachable-routines. Chris Pressey 2 years ago
6 changed file(s) with 71 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
1010 * A routine can be declared `preserved`, which prevents a
1111 compiler from omitting it from the final executable, even
1212 if it determines it is not called by any other routine.
13 * Added `--prune-unreachable-routines` option, which causes
14 the compiler to in fact omit routines determined to be
15 unreachable as described above.
1316 * The `dcc6502-adapter` test adapter was updated to conform
1417 to the output of the latest version of `dcc6502`.
1518
9494 Currently the `if` generator is not smart enough to avoid generating silly
9595 jump instructions. (See the Fallthru tests.) Improve it.
9696
97 ### Dead code removal
98
99 Once we have a call graph we can omit routines that we're sure aren't called.
100
101 This would let us use include-files and standard-libraries nicely: any
102 routines they define, but that you don't use, don't get included.
103
10497 Implementation
10598 --------------
10699
108101
109102 For analysis errors, there is a line number, but it's the line of the routine
110103 after the routine in which the analysis error occurred. Fix this.
104
105 ### Libraries
106
107 Now that we have dead-code removal, establish some libraries of reusable
108 routines.
111109
112110 Blue-skying
113111 -----------
1818 from sixtypical.symtab import SymbolTable
1919 from sixtypical.parser import Parser, merge_programs
2020 from sixtypical.analyzer import Analyzer
21 from sixtypical.callgraph import construct_callgraph, prune_unreachable_routines
2122 from sixtypical.outputter import outputter_class_for
2223 from sixtypical.compiler import Compiler
2324
4647 analyzer.analyze_program(program)
4748 finally:
4849 if options.dump_exit_contexts:
49 sys.stdout.write(json.dumps(analyzer.exit_contexts_map, indent=4, sort_keys=True, separators=(',', ':')))
50 sys.stdout.write(json.dumps(analyzer.exit_contexts_map, indent=4, sort_keys=True, separators=(',', ': ')))
5051 sys.stdout.write("\n")
5152
53 callgraph = construct_callgraph(program)
5254 if options.dump_callgraph:
53 from sixtypical.callgraph import construct_callgraph
54 graph = construct_callgraph(program)
55 sys.stdout.write(json.dumps(graph, indent=4, sort_keys=True, separators=(',', ': ')))
55 sys.stdout.write(json.dumps(callgraph, indent=4, sort_keys=True, separators=(',', ': ')))
56 if options.prune_unreachable_routines:
57 program = prune_unreachable_routines(program, callgraph)
5658
5759 compilation_roster = None
5860 if options.optimize_fallthru:
166168 help="Dump the ordered fallthru map, in JSON, to stdout after analyzing the program."
167169 )
168170 argparser.add_argument(
171 "--prune-unreachable-routines",
172 action="store_true",
173 help="Omit code for unreachable routines (as determined by the callgraph) "
174 "from the final output."
175 )
176 argparser.add_argument(
169177 "--dump-callgraph",
170178 action="store_true",
171179 help="Dump the call graph, in JSON, to stdout after analyzing the program."
0 from sixtypical.ast import Program
01 from sixtypical.model import RoutineType, VectorType
12
23
5758 mark_as_reachable(graph, routine.name)
5859
5960 return graph
61
62
63 def prune_unreachable_routines(program, callgraph):
64 return Program(1, defns=program.defns, routines=[
65 r for r in program.routines if callgraph[r.name].get('reachable', False)
66 ])
182182 = ]
183183 = }
184184 = }
185
186 -> Tests for functionality "Compile SixtyPical program with unreachable routine removal"
187
188 Basic test for actually removing unreachable routines from the resulting
189 executable when compiling SixtyPical programs.
190
191 | define main routine outputs a trashes z, n
192 | {
193 | ld a, 100
194 | }
195 |
196 | define other1 routine
197 | {
198 | call other2
199 | }
200 |
201 | define other2 routine
202 | {
203 | call other1
204 | }
205 = $080D LDA #$64
206 = $080F RTS
207
208 Test that marking routine as `preserved` preserves it in the output.
209
210 | define main routine outputs a trashes z, n
211 | {
212 | ld a, 100
213 | }
214 |
215 | define other preserved routine outputs a trashes z, n
216 | {
217 | ld a, 5
218 | }
219 = $080D LDA #$64
220 = $080F RTS
221 = $0810 LDA #$05
222 = $0812 RTS
1212 -> Functionality "Compile SixtyPical program" is implemented by
1313 -> shell command "bin/sixtypical --output-format=c64-basic-prg --traceback %(test-body-file) --output /tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo"
1414
15 -> Functionality "Dump callgraph info for SixtyPical program" is implemented by
16 -> shell command "bin/sixtypical --dump-callgraph --analyze-only --traceback %(test-body-file)"
17
18 -> Functionality "Compile SixtyPical program with unreachable routine removal" is implemented by
19 -> shell command "bin/sixtypical --output-format=c64-basic-prg --prune-unreachable-routines --traceback %(test-body-file) --output /tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo"
20
1521 -> Functionality "Dump fallthru info for SixtyPical program" is implemented by
1622 -> shell command "bin/sixtypical --optimize-fallthru --dump-fallthru-info --analyze-only --traceback %(test-body-file)"
1723
18 -> Functionality "Dump callgraph info for SixtyPical program" is implemented by
19 -> shell command "bin/sixtypical --dump-callgraph --analyze-only --traceback %(test-body-file)"
20
2124 -> Functionality "Compile SixtyPical program with fallthru optimization" is implemented by
2225 -> shell command "bin/sixtypical --output-format=c64-basic-prg --optimize-fallthru --traceback %(test-body-file) --output /tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo"