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

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 comments Created 9 years, 1 month 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
robertm 2011/11/28 19:44:04 are these all needed?
jvoung - send to chromium... 2011/11/28 20:14:25 Removed a few more.
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):
34 """PnaclGen generates shim code to bridge the Gcc ABI with PNaCl.
35
36 This subclass of WrapperGenerator takes the IDL sources and
37 generates shim methods for bridging the calling conventions between GCC
38 and PNaCl (LLVM). Some of the PPAPI methods do not need shimming, so
39 this will also detect those situations and provide direct access to the
40 original PPAPI methods (rather than the shim methods).
41 """
42
43 def __init__(self):
44 WrapperGen.__init__(self,
45 'Pnacl',
46 'Pnacl Shim Gen',
47 'pnacl',
48 'Generate the PNaCl shim.')
49 self.cgen = CGen()
50 self._skip_opt = False
51 self._pnacl_attribute = '__attribute__((pnaclcall))'
52
53
54 ############################################################
55
56 def InterfaceNeedsWrapper(self, iface, releases):
57 """Return true if the interface has ANY methods that need wrapping.
58 """
59 if self._skip_opt:
60 return True
61 for release in iface.GetUniqueReleases(releases):
62 version = iface.GetVersion(release)
63 if self.InterfaceVersionNeedsWrapping(iface, version):
64 return True
65 return False
66
67
68 def InterfaceVersionNeedsWrapping(self, iface, version):
69 """Return true if the interface+version has ANY methods that
70 need wrapping.
71 """
72 if self._skip_opt:
73 return True
74 for member in iface.GetListOf('Member'):
75 release = member.GetRelease(version)
76 if self.MemberNeedsWrapping(member, release):
77 return True
78 return False
79
80
81 def MemberNeedsWrapping(self, member, release):
82 """Return true if a particular member function at a particular
83 release needs wrapping.
84 """
85 if self._skip_opt:
86 return True
87 if not member.InReleases([release]):
88 return False
89 ret, name, array, args_spec = self.cgen.GetComponents(member,
90 release,
91 'store')
92 return self.TypeNeedsWrapping(ret, []) or self.ArgsNeedWrapping(args_spec)
93
94
95 def ArgsNeedWrapping(self, args):
96 """Return true if any parameter in the list needs wrapping.
97 """
98 for arg in args:
99 (type_str, name, array_dims, more_args) = arg
100 if self.TypeNeedsWrapping(type_str, array_dims):
101 return True
102 return False
103
104
105 def TypeNeedsWrapping(self, type_node, array_dims):
106 """Return true if a parameter type needs wrapping.
107 Currently, this is true for byval aggregates.
108 """
109 is_aggregate = type_node.startswith('struct') or \
110 type_node.startswith('union')
111 is_reference = (type_node.find('*') != -1 or array_dims != [])
112 return is_aggregate and not is_reference
113
114 ############################################################
115
116
117 def GenerateWrapperForPPBMethod(self, iface, member):
118 result = []
119 func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
120 sig = self.cgen.GetSignature(member, iface.release, 'store',
121 func_prefix, False)
122 result.append('static %s\n%s {\n' % (self._pnacl_attribute, sig))
123 result.append(' const struct %s *iface = %s.real_iface;\n' %
124 (iface.struct_name, self.GetWrapperInfoName(iface)))
125 ret, name, array, cspec = self.cgen.GetComponents(member,
126 iface.release,
127 'store')
128 ret_str, args_str = self.GetReturnArgs(ret, cspec)
129 result.append(' %siface->%s(%s);\n}\n\n' % (ret_str,
130 member.GetName(), args_str))
131 return result
132
133
134 def GenerateWrapperForPPPMethod(self, iface, member):
135 result = []
136 func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
137 sig = self.cgen.GetSignature(member, iface.release, 'store',
138 func_prefix, False)
139 result.append('static %s {\n' % sig)
140 result.append(' const struct %s *iface = %s.real_iface;\n' %
141 (iface.struct_name, self.GetWrapperInfoName(iface)))
142 temp_fp = self.cgen.GetSignature(member, iface.release, 'return',
143 'temp_fp',
144 func_as_ptr=True,
145 ptr_prefix=self._pnacl_attribute + ' ',
146 include_name=False)
147 cast = self.cgen.GetSignature(member, iface.release, 'return',
148 prefix='',
149 func_as_ptr=True,
150 ptr_prefix=self._pnacl_attribute + ' ',
151 include_name=False)
152 result.append(' %s = ((%s)iface->%s);\n' % (temp_fp,
153 cast,
154 member.GetName()))
155 ret, name, array, cspec = self.cgen.GetComponents(member,
156 iface.release,
157 'store')
158 ret_str, args_str = self.GetReturnArgs(ret, cspec)
159 result.append(' %stemp_fp(%s);\n}\n\n' % (ret_str, args_str))
160 return result
161
162
163 def GenerateRange(self, ast, releases, options):
164 """Generate shim code for a range of releases.
165 """
166 self._skip_opt = GetOption('disable_pnacl_opt')
167 self.SetOutputFile(GetOption('pnaclshim'))
168 return WrapperGen.GenerateRange(self, ast, releases, options)
169
170 pnaclgen = PnaclGen()
171
172 ######################################################################
173 # Tests.
174
175 # Clean a string representing an object definition and return then string
176 # as a single space delimited set of tokens.
177 def CleanString(instr):
178 instr = instr.strip()
179 instr = instr.split()
180 return ' '.join(instr)
181
182
183 def PrintErrorDiff(old, new):
184 oldlines = old.split(';')
185 newlines = new.split(';')
186 d = difflib.Differ()
187 diff = d.compare(oldlines, newlines)
188 ErrOut.Log('Diff is:\n%s' % '\n'.join(diff))
189
190
191 def GetOldTestOutput(ast):
192 # Scan the top-level comments in the IDL file for comparison.
193 old = []
194 for filenode in ast.GetListOf('File'):
195 for node in filenode.GetChildren():
196 instr = node.GetOneOf('Comment')
197 if not instr: continue
198 instr.Dump()
199 old.append(instr.GetName())
200 return CleanString(''.join(old))
201
202
203 def TestFiles(filenames, test_releases):
204 ast = ParseFiles(filenames)
205 iface_releases = pnaclgen.DetermineInterfaces(ast, test_releases)
206 new_output = CleanString(pnaclgen.GenerateWrapperForMethods(
207 iface_releases, comments=False))
208 old_output = GetOldTestOutput(ast)
209 if new_output != old_output:
210 PrintErrorDiff(old_output, new_output)
211 ErrOut.Log('Failed pnacl generator test.')
212 return 1
213 else:
214 InfoOut.Log('Passed pnacl generator test.')
215 return 0
216
217
218 def Main(args):
219 filenames = ParseOptions(args)
220 test_releases = ['M13', 'M14', 'M15']
221 if not filenames:
222 idldir = os.path.split(sys.argv[0])[0]
223 idldir = os.path.join(idldir, 'test_gen_pnacl', '*.idl')
224 filenames = glob.glob(idldir)
225 filenames = sorted(filenames)
226 if GetOption('test'):
227 # Run the tests.
228 return TestFiles(filenames, test_releases)
229
230 # Otherwise, generate the output file (for potential use as golden file).
231 ast = ParseFiles(filenames)
232 return pnaclgen.GenerateRange(ast, test_releases, filenames)
233
234
235 if __name__ == '__main__':
236 retval = Main(sys.argv[1:])
237 sys.exit(retval)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698