diff options
Diffstat (limited to 'src/mapi/mapi/mapi_abi.py')
-rw-r--r-- | src/mapi/mapi/mapi_abi.py | 257 |
1 files changed, 179 insertions, 78 deletions
diff --git a/src/mapi/mapi/mapi_abi.py b/src/mapi/mapi/mapi_abi.py index 3a872666f9..5c212420a8 100644 --- a/src/mapi/mapi/mapi_abi.py +++ b/src/mapi/mapi/mapi_abi.py @@ -45,6 +45,7 @@ class ABIEntry(object): self.slot = attrs['slot'] self.hidden = attrs['hidden'] self.alias = attrs['alias'] + self.handcode = attrs['handcode'] def c_prototype(self): return '%s %s(%s)' % (self.c_return(), self.name, self.c_params()) @@ -132,6 +133,7 @@ def abi_parse_line(line): 'slot': -1, 'hidden': False, 'alias': None, + 'handcode': None, } # extract attributes from the first column @@ -144,6 +146,8 @@ def abi_parse_line(line): attrs['hidden'] = True elif val.startswith('alias='): attrs['alias'] = val[6:] + elif val.startswith('handcode='): + attrs['handcode'] = val[9:] elif not val: pass else: @@ -166,10 +170,13 @@ def abi_parse(filename): # post-process attributes if attrs['alias']: try: - ent = entry_dict[attrs['alias']] - slot = ent.slot + alias = entry_dict[attrs['alias']] except KeyError: raise Exception('failed to alias %s' % attrs['alias']) + if alias.alias: + raise Exception('recursive alias %s' % ent.name) + slot = alias.slot + attrs['alias'] = alias else: slot = next_slot next_slot += 1 @@ -194,8 +201,15 @@ def abi_parse(filename): raise Exception('entries are not ordered by slots') if entries[i].alias: raise Exception('first entry of slot %d aliases %s' - % (slot, entries[i].alias)) + % (slot, entries[i].alias.name)) + handcode = None while i < len(entries) and entries[i].slot == slot: + ent = entries[i] + if not handcode and ent.handcode: + handcode = ent.handcode + elif ent.handcode != handcode: + raise Exception('two aliases with handcode %s != %s', + ent.handcode, handcode) i += 1 if i < len(entries): raise Exception('there are %d invalid entries' % (len(entries) - 1)) @@ -222,15 +236,37 @@ class ABIPrinter(object): self.api_entry = 'KHRONOS_APIENTRY' self.api_attrs = 'KHRONOS_APIATTRIBUTES' - def c_header(self): + self.lib_need_table_size = True + self.lib_need_noop_array = True + self.lib_need_stubs = True + self.lib_need_entries = True + + def c_notice(self): return '/* This file is automatically generated by mapi_abi.py. Do not modify. */' - def c_includes(self): + def c_public_includes(self): """Return includes of the client API headers.""" defines = ['#define ' + d for d in self.api_defines] includes = ['#include ' + h for h in self.api_headers] return "\n".join(defines + includes) + def need_entry_point(self, ent): + """Return True if an entry point is needed for the entry.""" + # non-handcode hidden aliases may share the entry they alias + use_alias = (ent.hidden and ent.alias and not ent.handcode) + return not use_alias + + def c_public_declarations(self, prefix): + """Return the declarations of public entry points.""" + decls = [] + for ent in self.entries: + if not self.need_entry_point(ent): + continue + export = self.api_call if not ent.hidden else '' + decls.append(self._c_decl(ent, prefix, True, export) + ';') + + return "\n".join(decls) + def c_mapi_table(self): """Return defines of the dispatch table size.""" num_static_entries = 0 @@ -244,8 +280,9 @@ class ABIPrinter(object): def c_mapi_table_initializer(self, prefix): """Return the array initializer for mapi_table_fill.""" - entries = [ent.name for ent in self.entries if not ent.alias] - pre = self.indent + '(mapi_proc) ' + prefix + entries = [self._c_function(ent, prefix) + for ent in self.entries if not ent.alias] + pre = self.indent + '(mapi_proc) ' return pre + (',\n' + pre).join(entries) def c_mapi_table_spec(self): @@ -263,11 +300,34 @@ class ABIPrinter(object): return self.indent + self.indent.join(specv1) - def _c_decl(self, ent, prefix, need_attr=True): + def _c_function(self, ent, prefix, mangle=False, stringify=False): + """Return the function name of an entry.""" + formats = { True: '"%s%s"', False: '%s%s' } + fmt = formats[stringify] + name = ent.name + if mangle and ent.hidden: + name = '_dispatch_stub_' + str(ent.slot) + return fmt % (prefix, name) + + def _c_function_call(self, ent, prefix): + """Return the function name used for calling.""" + if ent.handcode: + # _c_function does not handle this case + fmt = '%s%s' + name = fmt % (prefix, ent.handcode) + elif self.need_entry_point(ent): + name = self._c_function(ent, prefix, True) + else: + name = self._c_function(ent.alias, prefix, True) + return name + + def _c_decl(self, ent, prefix, mangle=False, export=''): """Return the C declaration for the entry.""" - decl = '%s %s %s%s(%s)' % (ent.c_return(), self.api_entry, - prefix, ent.name, ent.c_params()) - if need_attr and self.api_attrs: + decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry, + self._c_function(ent, prefix, mangle), ent.c_params()) + if export: + decl = export + ' ' + decl + if self.api_attrs: decl += ' ' + self.api_attrs return decl @@ -281,19 +341,21 @@ class ABIPrinter(object): def c_private_declarations(self, prefix): """Return the declarations of private functions.""" - decls = [self._c_decl(ent, prefix) + decls = [self._c_decl(ent, prefix) + ';' for ent in self.entries if not ent.alias] - return ";\n".join(decls) + ";" + return "\n".join(decls) def c_public_dispatches(self, prefix): """Return the public dispatch functions.""" dispatches = [] for ent in self.entries: - if ent.hidden: + if not self.need_entry_point(ent): continue - proto = self.api_call + ' ' + self._c_decl(ent, prefix) + export = self.api_call if not ent.hidden else '' + + proto = self._c_decl(ent, prefix, True, export) cast = self._c_cast(ent) ret = '' @@ -308,10 +370,27 @@ class ABIPrinter(object): stmt3 += '%s((%s) func)(%s);' % (ret, cast, ent.c_args()) disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3) + + if ent.handcode: + disp = '#if 0\n' + disp + '\n#endif' + dispatches.append(disp) return '\n\n'.join(dispatches) + def c_public_initializer(self, prefix): + """Return the initializer for public dispatch functions.""" + names = [] + for ent in self.entries: + if ent.alias: + continue + + name = '%s(mapi_func) %s' % (self.indent, + self._c_function_call(ent, prefix)) + names.append(name) + + return ',\n'.join(names) + def c_stub_string_pool(self): """Return the string pool for use by stubs.""" # sort entries by their names @@ -334,8 +413,8 @@ class ABIPrinter(object): """Return the initializer for struct mapi_stub array.""" stubs = [] for ent in self.entries_sorted_by_names: - stubs.append('%s{ (mapi_func) %s%s, %d, (void *) %d }' % ( - self.indent, prefix, ent.name, ent.slot, pool_offsets[ent])) + stubs.append('%s{ (void *) %d, %d, NULL }' % ( + self.indent, pool_offsets[ent], ent.slot)) return ',\n'.join(stubs) @@ -346,10 +425,10 @@ class ABIPrinter(object): if ent.alias: continue - proto = 'static ' + self._c_decl(ent, prefix) + proto = self._c_decl(ent, prefix, False, 'static') - stmt1 = self.indent + '%s("%s%s");' % ( - self.noop_warn, warn_prefix, ent.name) + stmt1 = self.indent + '%s(%s);' % (self.noop_warn, + self._c_function(ent, warn_prefix, False, True)) if ent.ret: stmt2 = self.indent + 'return (%s) 0;' % (ent.ret) @@ -363,7 +442,8 @@ class ABIPrinter(object): def c_noop_initializer(self, prefix, use_generic): """Return an initializer for the noop dispatch table.""" - entries = [prefix + ent.name for ent in self.entries if not ent.alias] + entries = [self._c_function(ent, prefix) + for ent in self.entries if not ent.alias] if use_generic: entries = [self.noop_generic] * len(entries) @@ -374,84 +454,105 @@ class ABIPrinter(object): def c_asm_gcc(self, prefix): asm = [] - to_name = None asm.append('__asm__(') for ent in self.entries: - name = prefix + ent.name + if not self.need_entry_point(ent): + continue + + name = self._c_function(ent, prefix, True, True) + + if ent.handcode: + asm.append('#if 0') if ent.hidden: - asm.append('".hidden %s\\n"' % (name)) + asm.append('".hidden "%s"\\n"' % (name)) if ent.alias: - asm.append('".globl %s\\n"' % (name)) - asm.append('".set %s, %s\\n"' % (name, to_name)) + asm.append('".globl "%s"\\n"' % (name)) + asm.append('".set "%s", "%s"\\n"' % (name, + self._c_function(ent.alias, prefix, True, True))) else: - asm.append('STUB_ASM_ENTRY("%s")"\\n"' % (name)) + asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name)) asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot)) - to_name = name + + if ent.handcode: + asm.append('#endif') + asm.append('') asm.append(');') return "\n".join(asm) def output_for_lib(self): - print self.c_header() + print self.c_notice() print print '#ifdef MAPI_TMP_DEFINES' - print self.c_includes() + print self.c_public_includes() + print + print self.c_public_declarations(self.prefix_lib) print '#undef MAPI_TMP_DEFINES' print '#endif /* MAPI_TMP_DEFINES */' - print - print '#ifdef MAPI_TMP_TABLE' - print self.c_mapi_table() - print '#undef MAPI_TMP_TABLE' - print '#endif /* MAPI_TMP_TABLE */' - print - - pool, pool_offsets = self.c_stub_string_pool() - print '#ifdef MAPI_TMP_PUBLIC_STUBS' - print 'static const char public_string_pool[] =' - print pool - print - print 'static const struct mapi_stub public_stubs[] = {' - print self.c_stub_initializer(self.prefix_lib, pool_offsets) - print '};' - print '#undef MAPI_TMP_PUBLIC_STUBS' - print '#endif /* MAPI_TMP_PUBLIC_STUBS */' - print - - print '#ifdef MAPI_TMP_PUBLIC_ENTRIES' - print self.c_public_dispatches(self.prefix_lib) - print '#undef MAPI_TMP_PUBLIC_ENTRIES' - print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */' - print - - print '#ifdef MAPI_TMP_NOOP_ARRAY' - print '#ifdef DEBUG' - print - print self.c_noop_functions(self.prefix_noop, self.prefix_lib) - print - print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) - print self.c_noop_initializer(self.prefix_noop, False) - print '};' - print - print '#else /* DEBUG */' - print - print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) - print self.c_noop_initializer(self.prefix_noop, True) - print '};' - print '#endif /* DEBUG */' - print '#undef MAPI_TMP_NOOP_ARRAY' - print '#endif /* MAPI_TMP_NOOP_ARRAY */' - print - print '#ifdef MAPI_TMP_STUB_ASM_GCC' - print self.c_asm_gcc(self.prefix_lib) - print '#undef MAPI_TMP_STUB_ASM_GCC' - print '#endif /* MAPI_TMP_STUB_ASM_GCC */' + if self.lib_need_table_size: + print + print '#ifdef MAPI_TMP_TABLE' + print self.c_mapi_table() + print '#undef MAPI_TMP_TABLE' + print '#endif /* MAPI_TMP_TABLE */' + + if self.lib_need_noop_array: + print + print '#ifdef MAPI_TMP_NOOP_ARRAY' + print '#ifdef DEBUG' + print + print self.c_noop_functions(self.prefix_noop, self.prefix_lib) + print + print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) + print self.c_noop_initializer(self.prefix_noop, False) + print '};' + print + print '#else /* DEBUG */' + print + print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) + print self.c_noop_initializer(self.prefix_noop, True) + print '};' + print + print '#endif /* DEBUG */' + print '#undef MAPI_TMP_NOOP_ARRAY' + print '#endif /* MAPI_TMP_NOOP_ARRAY */' + + if self.lib_need_stubs: + pool, pool_offsets = self.c_stub_string_pool() + print + print '#ifdef MAPI_TMP_PUBLIC_STUBS' + print 'static const char public_string_pool[] =' + print pool + print + print 'static const struct mapi_stub public_stubs[] = {' + print self.c_stub_initializer(self.prefix_lib, pool_offsets) + print '};' + print '#undef MAPI_TMP_PUBLIC_STUBS' + print '#endif /* MAPI_TMP_PUBLIC_STUBS */' + + if self.lib_need_entries: + print + print '#ifdef MAPI_TMP_PUBLIC_ENTRIES' + print self.c_public_dispatches(self.prefix_lib) + print + print 'static const mapi_func public_entries[] = {' + print self.c_public_initializer(self.prefix_lib) + print '};' + print '#undef MAPI_TMP_PUBLIC_ENTRIES' + print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */' + + print + print '#ifdef MAPI_TMP_STUB_ASM_GCC' + print self.c_asm_gcc(self.prefix_lib) + print '#undef MAPI_TMP_STUB_ASM_GCC' + print '#endif /* MAPI_TMP_STUB_ASM_GCC */' def output_for_app(self): - print self.c_header() + print self.c_notice() print print self.c_private_declarations(self.prefix_app) print |