Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: src/trusted/validator_arm/dgen_output.py

Issue 9960043: Finish separation of testing from sel_ldr validation. Also, automate (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/trusted/validator_arm/dgen_input.py ('k') | src/trusted/validator_arm/dgen_test_output.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright 2012 The Native Client Authors. All rights reserved. 3 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can 4 # Use of this source code is governed by a BSD-style license that can be
5 # be found in the LICENSE file. 5 # found in the LICENSE file.
6 # 6 #
7 7
8 """ 8 """
9 Responsible for generating the decoder based on parsed table representations. 9 Some common boilerplates and helper functions for source code generation
10 in files dgen_test_output.py and dgen_decode_output.py.
10 """ 11 """
11 12
12 import dgen_opt 13 HEADER_BOILERPLATE ="""
14 /*
15 * Copyright 2012 The Native Client Authors. All rights reserved.
16 * Use of this source code is governed by a BSD-style license that can
17 * be found in the LICENSE file.
18 */
13 19
14 def generate_decoder_h(tables, decoder_name, filename, named_decoders, out): 20 // DO NOT EDIT: GENERATED CODE
15 """Entry point to the decoder for .h file. 21 """
16 22
17 Args: 23 NOT_TCB_BOILERPLATE="""
18 tables: list of Table objects to process. 24 #ifndef NACL_TRUSTED_BUT_NOT_TCB
19 decoder_name: The name of the decoder state to build. 25 #error This file is not meant for use in the TCB
20 filename: The (localized) name for the .h file. 26 #endif
21 named_decoders: If true, generate a decoder state with named instances.
22 out: a COutput object to write to.
23 """
24 if len(tables) == 0: raise Exception('No tables provided.')
25 27
26 ifdef_name = _generate_ifdef_name(filename) 28 """
27 named_prefix = ''
28 if named_decoders:
29 named_prefix = 'Named'
30 29
31 _generate_header(out) 30 def ifdef_name(filename):
32 out.line() 31 """ Generates the ifdef name to use for the given filename"""
33 out.line("#ifndef %s" % ifdef_name)
34 out.line("#define %s" % ifdef_name)
35 out.line()
36 out.line('#include "native_client/src/trusted/validator_arm/decode.h"')
37 out.line()
38 out.line('namespace nacl_arm_dec {')
39 out.line()
40 if named_decoders:
41 _generate_named_decoder_classes(tables, named_prefix, out)
42 _generate_decoder_state_type(tables, decoder_name, named_prefix, out)
43 out.line('} // namespace')
44 out.line("#endif // %s" % ifdef_name)
45
46
47 def generate_decoder_cc(tables, decoder_name, filename, named_decoders, out):
48 """Entry point to the decoder for .cc file
49
50 Args:
51 tables: list of Table objects to process.
52 decoder_name: The name of the decoder state to build.
53 filename: The (localized) name for the .h file.
54 named_decoders: If true, generate a decoder state with named instances.
55 out: a COutput object to write to.
56 """
57 if len(tables) == 0: raise Exception('No tables provided.')
58
59 named_prefix = ''
60 if named_decoders:
61 named_prefix = 'Named'
62
63 _generate_header(out)
64 out.line()
65 out.line('#include "%s"' % (filename[:-2] + 'h'))
66 out.line();
67 out.line('#include <stdio.h>')
68 out.line()
69 out.line('namespace nacl_arm_dec {')
70 out.line()
71 if named_decoders:
72 _generate_named_decoder_classes_impls(tables, named_prefix, out)
73 _generate_prototypes(tables, decoder_name, named_prefix, out)
74 _generate_implementations(tables, decoder_name, named_prefix, out)
75 _generate_constructors(tables, decoder_name, named_prefix, out)
76 _generate_entry_point(decoder_name, named_prefix, tables[0].name, out)
77 out.line('} // namespace')
78
79
80 def _generate_ifdef_name(filename):
81 return filename.replace("/", "_").replace(".", "_").upper() + "_" 32 return filename.replace("/", "_").replace(".", "_").upper() + "_"
82
83 def _generate_header(out):
84 out.block_comment(
85 'Copyright 2012 The Native Client Authors. All rights reserved.',
86 'Use of this source code is governed by a BSD-style license that can',
87 'be found in the LICENSE file.',
88 )
89 out.line()
90 out.block_comment('DO NOT EDIT: GENERATED CODE')
91
92 def _table_terminals(tables):
93 terminals = set()
94 for t in tables:
95 for r in t.rows:
96 if r.action.startswith('='):
97 terminals.add(r.action[1:])
98 return terminals
99
100 def _generate_named_decoder_classes(tables, named_prefix, out):
101 for t in _table_terminals(tables):
102 out.enter_block('struct %s%s : public %s' % (named_prefix, t, t))
103 out.line('virtual ~%s%s() {}' % (named_prefix, t))
104 out.line('virtual const char* name() const;')
105 out.exit_block(';')
106 out.line()
107
108 def _generate_named_decoder_classes_impls(tables, named_prefix, out):
109 for t in _table_terminals(tables):
110 out.enter_block('const char* %s%s::name() const' % (named_prefix, t));
111 out.line('return "%s";' % t)
112 out.exit_block()
113 out.line()
114
115 def _generate_decoder_state_type(tables, decoder_name, named_prefix, out):
116 cls_name = '%s%s' % (named_prefix, decoder_name)
117 out.block_comment(
118 'Defines a stateless decoder class selector for instructions'
119 )
120 out.block_comment('Define the class decoders used by this decoder state.')
121 out.enter_block('class %s : DecoderState' % cls_name)
122 out.visibility('public')
123 out.comment('Generates an instance of a decoder state.')
124 out.line('explicit %s();' % cls_name)
125 out.line('virtual ~%s();' % cls_name)
126 out.line()
127 out.comment('Parses the given instruction, returning the decoder to use.')
128 out.line('virtual const class ClassDecoder '
129 '&decode(const Instruction) const;')
130 out.line()
131 out.comment('Define the decoders to use in this decoder state')
132 for t in _table_terminals(tables):
133 out.line('%s%s %s_instance_;' % (named_prefix, t, t))
134 out.line()
135 out.visibility('private')
136 out.comment("Don't allow the following!")
137 out.line('explicit %s(const %s&);' % (cls_name, cls_name))
138 out.line('void operator=(const %s&);' % cls_name)
139 out.exit_block(';')
140 out.line()
141
142 def _generate_prototypes(tables, decoder_name, named_prefix, out):
143 out.block_comment('Prototypes for static table-matching functions.')
144 for t in tables:
145
146 out.line('static inline const ClassDecoder &decode_%s(' % t.name)
147 out.line(' const Instruction insn, const %s%s *state);' %
148 (named_prefix, decoder_name))
149 out.line()
150
151 def _generate_implementations(tables, decoder_name, named_prefix, out):
152 out.block_comment('Table-matching function implementations.')
153 for t in tables:
154 out.line()
155 _generate_table(t, decoder_name, named_prefix, out)
156 out.line()
157
158 def _generate_constructors(tables, decoder_name, named_prefix, out):
159 out.enter_constructor_header('%s%s::%s%s()' % (named_prefix, decoder_name,
160 named_prefix, decoder_name))
161 out.line('DecoderState()')
162 for t in _table_terminals(tables):
163 out.line(', %s_instance_()' % t)
164 out.exit_constructor_header()
165 out.enter_block()
166 out.exit_block()
167 out.line()
168 out.enter_block('%s%s::~%s%s()' % (named_prefix, decoder_name,
169 named_prefix, decoder_name))
170 out.exit_block()
171 out.line()
172
173 def _generate_entry_point(decoder_name, named_prefix, initial_table_name, out):
174 out.enter_block(
175 'const ClassDecoder &%s%s::decode(const Instruction insn) const' %
176 (named_prefix, decoder_name))
177 out.line('return decode_%s(insn, this);'
178 % initial_table_name)
179 out.exit_block()
180 out.line()
181
182
183 def _generate_table(table, decoder_name, named_prefix, out):
184 """Generates the implementation of a single table."""
185 out.block_comment(
186 'Implementation of table %s.' % table.name,
187 'Specified by: %s.' % table.citation
188 )
189 out.line('static inline const ClassDecoder &decode_%s(' %table.name)
190 out.enter_block(' const Instruction insn, const %s%s *state)' %
191 (named_prefix, decoder_name))
192
193 optimized = dgen_opt.optimize_rows(table.rows)
194 print ("Table %s: %d rows minimized to %d"
195 % (table.name, len(table.rows), len(optimized)))
196 for row in sorted(optimized):
197 exprs = ["(%s)" % p.to_c_expr('insn') for p in row.patterns]
198 out.enter_block('if (%s)' % ' && '.join(exprs))
199
200 if row.action.startswith('='):
201 _generate_terminal(row.action[1:], out)
202 elif row.action.startswith('->'):
203 _generate_table_change(row.action[2:], out)
204 else:
205 raise Exception('Bad table action: %s' % row.action)
206
207 out.exit_block()
208 out.line()
209
210 _generate_safety_net(table, out)
211 out.exit_block()
212
213 def _generate_terminal(name, out):
214 out.line('return state->%s_instance_;' % name)
215
216 def _generate_table_change(name, out):
217 out.line('return decode_%s(insn, state);' % name)
218
219 def _generate_safety_net(table, out):
220 out.line('// Catch any attempt to fall through...')
221 out.line('fprintf(stderr, "TABLE IS INCOMPLETE: %s could not parse %%08X",'
222 'insn.bits(31,0));' % table.name)
223 _generate_terminal('Forbidden', out)
224
225
226 class COutput(object):
227 """Provides nicely-formatted C++ output."""
228
229 def __init__(self, out):
230 self._out = out
231 self._indent = 0
232
233 def line(self, str = ''):
234 self._out.write(self._tabs())
235 self._out.write(str + '\n')
236
237 def enter_constructor_header(self, headline):
238 self.line(headline + ' :')
239 self._indent += 1
240
241 def exit_constructor_header(self):
242 self._indent -= 1
243
244 def visibility(self, spec):
245 self._indent -= 1
246 self.line(' %s:' % spec)
247 self._indent += 1
248
249 def comment(self, line_comment):
250 self.line('// %s' % line_comment)
251
252 def enter_block(self, headline=''):
253 self.line(headline + ' {')
254 self._indent += 1
255
256 def exit_block(self, footer = ''):
257 self._indent -= 1
258 self.line('}' + footer)
259
260 def block_comment(self, *lines):
261 self.line('/*')
262 for s in lines:
263 self.line(' * ' + s)
264 self.line(' */')
265
266 def _tabs(self):
267 return ' ' * self._indent
268
269
270 def each_index_pair(sequence):
271 """Utility method: Generates each unique index pair in sequence."""
272 for i in range(0, len(sequence)):
273 for j in range(i + 1, len(sequence)):
274 yield (i, j)
OLDNEW
« no previous file with comments | « src/trusted/validator_arm/dgen_input.py ('k') | src/trusted/validator_arm/dgen_test_output.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698