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

Side by Side Diff: ppapi/generators/idl_gen_pnacl.py

Issue 8568025: Pnacl ppapi shim generator (from IDL), based on Noel's first cut. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix presubmit.wq Created 9 years 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
OLDNEW
(Empty)
1 #!/usr/bin/python
2 #
3 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 """ Generator for Pnacl Shim functions that bridges the calling conventions
8 between GCC and PNaCl. """
9
10 from datetime import datetime
11 import difflib
12 import glob
13 import os
14 import sys
15
16 from idl_ast import IDLAst
17 from idl_c_proto import CGen
18 from idl_generator import Generator
19 from idl_gen_wrapper import Interface, WrapperGen
20 from idl_log import ErrOut, InfoOut, WarnOut
21 from idl_option import GetOption, Option, ParseOptions
22 from idl_outfile import IDLOutFile
23 from idl_parser import ParseFiles
24
25 Option('pnaclshim', 'Name of the pnacl shim file.',
26 default='temp_pnacl_shim.c')
27
28
29 # TODO(jvoung): this doesn't do anything yet (except change some dbg messages).
30 Option('disable_pnacl_opt', 'Turn off optimization of pnacl shim.')
31
32
33 class PnaclGen(WrapperGen):
noelallen1 2011/11/23 18:06:11 Python style is: """One line description. Followe
jvoung - send to chromium... 2011/11/23 22:39:28 Done.
34 """PnaclGen - A subclass of WrapperGenerator which takes the IDL sources and
35 generates shim code for bridging the calling conventions between GCC
36 and PNaCl (LLVM).
37 """
38
39 def __init__(self):
40 WrapperGen.__init__(self,
41 'Pnacl',
42 'Pnacl Shim Gen',
43 'pnacl',
44 'Generate the PNaCl shim.')
45 self.cgen = CGen()
46 self._skip_opt = False
47 self._pnacl_attribute = '__attribute__((pnaclcall))'
48
49
50 ############################################################
51
52 def InterfaceNeedsWrapper(self, iface, releases):
53 """ Return true if the interface has ANY methods that need wrapping. """
54 if self._skip_opt:
55 return True
56 for release in iface.GetUniqueReleases(releases):
57 version = iface.GetVersion(release)
58 if self.InterfaceVersionNeedsWrapping(iface, version):
59 return True
60 return False
61
62
63 def InterfaceVersionNeedsWrapping(self, iface, version):
64 """ Return true if the interface+version has ANY methods that
65 need wrapping. """
66 if self._skip_opt:
67 return True
68 for member in iface.GetListOf('Member'):
69 release = member.GetRelease(version)
70 if self.MemberNeedsWrapping(member, release):
71 return True
72 return False
73
74
75 def MemberNeedsWrapping(self, member, release):
76 """ Return true if a particular member function at a particular
77 release needs wrapping. """
78 if self._skip_opt:
79 return True
80 if not member.InReleases([release]):
81 return False
82 ret, name, array, args_spec = self.cgen.GetComponents(member,
83 release,
84 'store')
85 return self.TypeNeedsWrapping(ret, []) or self.ArgsNeedWrapping(args_spec)
86
87
88 def ArgsNeedWrapping(self, args):
89 """ Return true if any parameter in the list needs wrapping. """
90 for arg in args:
91 (type_str, name, array_dims, more_args) = arg
92 if self.TypeNeedsWrapping(type_str, array_dims):
93 return True
94 return False
95
96
97 def TypeNeedsWrapping(self, type_node, array_dims):
98 """ Return true if a parameter type needs wrapping.
99 Currently, this is true for byval aggregates. """
100 is_aggregate = type_node.startswith('struct') or \
101 type_node.startswith('union')
102 is_reference = (type_node.find('*') != -1 or array_dims != [])
103 return is_aggregate and not is_reference
104
105 ############################################################
106
107
108 def GenerateWrapperForPPBMethod(self, iface, member):
109 result = []
110 func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
111 sig = self.cgen.GetSignature(member, iface.release, 'store',
112 func_prefix, False)
113 result.append('static %s\n%s {\n' % (self._pnacl_attribute, sig))
114 result.append(' const struct %s *iface = %s.real_iface;\n' %
115 (iface.struct_name, self.GetWrapperInfoName(iface)))
116 ret, name, array, cspec = self.cgen.GetComponents(member,
117 iface.release,
118 'store')
119 ret_str, args_str = self.GetReturnArgs(ret, cspec)
120 result.append(' %siface->%s(%s);\n}\n\n' % (ret_str,
121 member.GetName(), args_str))
122 return result
123
124
125 def GenerateWrapperForPPPMethod(self, iface, member):
126 result = []
127 func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
128 sig = self.cgen.GetSignature(member, iface.release, 'store',
129 func_prefix, False)
130 result.append('static %s {\n' % sig)
131 result.append(' const struct %s *iface = %s.real_iface;\n' %
132 (iface.struct_name, self.GetWrapperInfoName(iface)))
133 temp_fp = self.cgen.GetSignature(member, iface.release, 'return',
134 'temp_fp',
135 func_as_ptr=True,
136 ptr_prefix=self._pnacl_attribute + ' ',
137 include_name=False)
138 cast = self.cgen.GetSignature(member, iface.release, 'return',
139 prefix='',
140 func_as_ptr=True,
141 ptr_prefix=self._pnacl_attribute + ' ',
142 include_name=False)
143 result.append(' %s = ((%s)iface->%s);\n' % (temp_fp,
144 cast,
145 member.GetName()))
146 ret, name, array, cspec = self.cgen.GetComponents(member,
147 iface.release,
148 'store')
149 ret_str, args_str = self.GetReturnArgs(ret, cspec)
150 result.append(' %stemp_fp(%s);\n}\n\n' % (ret_str, args_str))
151 return result
152
153
154 def GenerateRange(self, ast, releases, options):
155 """ Generate shim code for a range of releases. """
156
157 self._skip_opt = GetOption('disable_pnacl_opt')
158 self.SetOutputFile(GetOption('pnaclshim'))
159 return WrapperGen.GenerateRange(self, ast, releases, options)
160
161 pnaclgen = PnaclGen()
162
163 ######################################################################
164 # Tests.
165
166 # Clean a string representing an object definition and return then string
167 # as a single space delimited set of tokens.
168 def CleanString(instr):
169 instr = instr.strip()
170 instr = instr.split()
171 return ' '.join(instr)
172
173
174 def PrintErrorDiff(old, new):
175 oldlines = old.split(';')
176 newlines = new.split(';')
177 d = difflib.Differ()
178 diff = d.compare(oldlines, newlines)
179 ErrOut.Log('Diff is:\n%s' % '\n'.join(diff))
180
181
182 def GetOldTestOutput(ast):
183 # Scan the top-level comments in the IDL file for comparison.
184 old = []
185 for filenode in ast.GetListOf('File'):
186 for node in filenode.GetChildren():
187 instr = node.GetOneOf('Comment')
188 if not instr: continue
189 instr.Dump()
190 old.append(instr.GetName())
191 return CleanString(''.join(old))
192
193
194 def TestFiles(filenames, test_releases):
195 ast = ParseFiles(filenames)
196 iface_releases = pnaclgen.DetermineInterfaces(ast, test_releases)
197 new_output = CleanString(pnaclgen.GenerateWrapperForMethods(
198 iface_releases, comments=False))
199 old_output = GetOldTestOutput(ast)
200 if new_output != old_output:
201 PrintErrorDiff(old_output, new_output)
202 ErrOut.Log('Failed pnacl generator test.')
203 return 1
204 else:
205 InfoOut.Log('Passed pnacl generator test.')
206 return 0
207
208
209 def Main(args):
210 filenames = ParseOptions(args)
211 test_releases = ['M13', 'M14', 'M15']
212 if not filenames:
213 idldir = os.path.split(sys.argv[0])[0]
214 idldir = os.path.join(idldir, 'test_gen_pnacl', '*.idl')
215 filenames = glob.glob(idldir)
216 filenames = sorted(filenames)
217 if GetOption('test'):
218 # Run the tests.
219 return TestFiles(filenames, test_releases)
220
221 # Otherwise, generate the output file (for potential use as golden file).
222 ast = ParseFiles(filenames)
223 return pnaclgen.GenerateRange(ast, test_releases, filenames)
224
225
226 if __name__ == '__main__':
227 retval = Main(sys.argv[1:])
228 sys.exit(retval)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698