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

Powered by Google App Engine
This is Rietveld 408576698