From d4589d381697b4b3dd291a3c93a34370508ef1e8 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 23 Apr 2010 16:07:47 +0800 Subject: [PATCH] mapi: Add a generic C dispatcher. The idea is to have an API generate a header using mapi_abi.py. The API can then use the header to build a dispatcher. --- src/mapi/mapi/entry.c | 52 +++++ src/mapi/mapi/entry.h | 49 +++++ src/mapi/mapi/mapi.c | 191 ++++++++++++++++++ src/mapi/mapi/mapi.h | 56 ++++++ src/mapi/mapi/mapi_abi.py | 402 ++++++++++++++++++++++++++++++++++++++ src/mapi/mapi/mapi_tmp.h | 186 ++++++++++++++++++ src/mapi/mapi/sources.mak | 13 ++ src/mapi/mapi/stub.c | 180 +++++++++++++++++ src/mapi/mapi/stub.h | 52 +++++ src/mapi/mapi/table.c | 56 ++++++ src/mapi/mapi/table.h | 76 +++++++ src/mapi/mapi/u_macros.h | 12 ++ 12 files changed, 1325 insertions(+) create mode 100644 src/mapi/mapi/entry.c create mode 100644 src/mapi/mapi/entry.h create mode 100644 src/mapi/mapi/mapi.c create mode 100644 src/mapi/mapi/mapi.h create mode 100644 src/mapi/mapi/mapi_abi.py create mode 100644 src/mapi/mapi/mapi_tmp.h create mode 100644 src/mapi/mapi/stub.c create mode 100644 src/mapi/mapi/stub.h create mode 100644 src/mapi/mapi/table.c create mode 100644 src/mapi/mapi/table.h create mode 100644 src/mapi/mapi/u_macros.h diff --git a/src/mapi/mapi/entry.c b/src/mapi/mapi/entry.c new file mode 100644 index 00000000000..b38df073918 --- /dev/null +++ b/src/mapi/mapi/entry.c @@ -0,0 +1,52 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include +#include "u_current.h" +#include "entry.h" +#include "table.h" + +/* C version of the public entries */ +#define MAPI_TMP_PUBLIC_ENTRIES +#include "mapi_tmp.h" + +void +entry_patch_public(void) +{ +} + +mapi_func +entry_generate(int slot) +{ + return NULL; +} + +void +entry_patch(mapi_func entry, int slot) +{ +} diff --git a/src/mapi/mapi/entry.h b/src/mapi/mapi/entry.h new file mode 100644 index 00000000000..48ed3f9ec4a --- /dev/null +++ b/src/mapi/mapi/entry.h @@ -0,0 +1,49 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef _ENTRY_H_ +#define _ENTRY_H_ + +#include "u_compiler.h" +#include "stub.h" + +/* declare public entries */ +#define MAPI_TMP_DEFINES +#define MAPI_TMP_PUBLIC_DECLARES +#include "mapi_tmp.h" + +void +entry_patch_public(void); + +mapi_func +entry_generate(int slot); + +void +entry_patch(mapi_func entry, int slot); + +#endif /* _ENTRY_H_ */ diff --git a/src/mapi/mapi/mapi.c b/src/mapi/mapi/mapi.c new file mode 100644 index 00000000000..2f1c3fff6cc --- /dev/null +++ b/src/mapi/mapi/mapi.c @@ -0,0 +1,191 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include +#include + +#include "u_current.h" +#include "u_thread.h" +#include "mapi.h" +#include "stub.h" +#include "table.h" + +/* dynamic stubs will run out before this array */ +#define MAPI_MAX_STUBS (sizeof(struct mapi_table) / sizeof(mapi_func)) +static const struct mapi_stub *mapi_stub_map[MAPI_MAX_STUBS]; +static int mapi_num_stubs; + +static const struct mapi_stub * +get_stub(const char *name, const struct mapi_stub *alias) +{ + const struct mapi_stub *stub; + + stub = stub_find_public(name); + if (!stub) { + struct mapi_stub *dyn = stub_find_dynamic(name, 1); + if (dyn) { + stub_fix_dynamic(dyn, alias); + stub = dyn; + } + } + + return stub; +} + +/** + * Initialize mapi. spec consists of NULL-separated strings. The first string + * denotes the version. It is followed by variable numbers of entries. Each + * entry can have multiple names. An empty name terminates an entry. An empty + * entry terminates the spec. A spec of two entries, Foo and Bar, is as + * follows + * + * "1\0" + * "Foo\0" + * "FooEXT\0" + * "\0" + * "Bar\0" + * "\0" + */ +void +mapi_init(const char *spec) +{ + u_mutex_declare_static(mutex); + const char *p; + int ver, count; + + u_mutex_lock(mutex); + + /* already initialized */ + if (mapi_num_stubs) { + u_mutex_unlock(mutex); + return; + } + + count = 0; + p = spec; + + /* parse version string */ + ver = atoi(p); + if (ver != 1) { + u_mutex_unlock(mutex); + return; + } + p += strlen(p) + 1; + + while (*p) { + const struct mapi_stub *stub; + + stub = get_stub(p, NULL); + /* out of dynamic entries */ + if (!stub) + break; + p += strlen(p) + 1; + + while (*p) { + get_stub(p, stub); + p += strlen(p) + 1; + } + + mapi_stub_map[count++] = stub; + p++; + } + + mapi_num_stubs = count; + + u_mutex_unlock(mutex); +} + +/** + * Return the address of an entry. Optionally generate the entry if it does + * not exist. + */ +mapi_proc +mapi_get_proc_address(const char *name) +{ + const struct mapi_stub *stub; + + stub = stub_find_public(name); + if (!stub) + stub = stub_find_dynamic(name, 0); + + return (stub) ? (mapi_proc) stub->addr : NULL; +} + +/** + * Create a dispatch table. + */ +struct mapi_table * +mapi_table_create(void) +{ + const struct mapi_table *noop = table_get_noop(); + struct mapi_table *tbl; + + tbl = malloc(sizeof(*tbl)); + if (tbl) + memcpy(tbl, noop, sizeof(*tbl)); + + return tbl; +} + +/** + * Destroy a dispatch table. + */ +void +mapi_table_destroy(struct mapi_table *tbl) +{ + free(tbl); +} + +/** + * Fill a dispatch table. The order of the procs is determined when mapi_init + * is called. + */ +void +mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs) +{ + const struct mapi_table *noop = table_get_noop(); + int i; + + for (i = 0; i < mapi_num_stubs; i++) { + const struct mapi_stub *stub = mapi_stub_map[i]; + mapi_func func = (mapi_func) procs[i]; + + if (!func) + func = table_get_func(noop, stub); + table_set_func(tbl, stub, func); + } +} + +/** + * Make a dispatch table current. + */ +void +mapi_table_make_current(const struct mapi_table *tbl) +{ + u_current_set(tbl); +} diff --git a/src/mapi/mapi/mapi.h b/src/mapi/mapi/mapi.h new file mode 100644 index 00000000000..8832b3dfb6e --- /dev/null +++ b/src/mapi/mapi/mapi.h @@ -0,0 +1,56 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef _MAPI_H_ +#define _MAPI_H_ + +#include "u_compiler.h" + +typedef void (*mapi_proc)(void); + +struct mapi_table; + +PUBLIC void +mapi_init(const char *spec); + +PUBLIC mapi_proc +mapi_get_proc_address(const char *name); + +PUBLIC struct mapi_table * +mapi_table_create(void); + +PUBLIC void +mapi_table_destroy(struct mapi_table *tbl); + +PUBLIC void +mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs); + +PUBLIC void +mapi_table_make_current(const struct mapi_table *tbl); + +#endif /* _MAPI_H_ */ diff --git a/src/mapi/mapi/mapi_abi.py b/src/mapi/mapi/mapi_abi.py new file mode 100644 index 00000000000..440eb4bb9c0 --- /dev/null +++ b/src/mapi/mapi/mapi_abi.py @@ -0,0 +1,402 @@ +#!/usr/bin/env python + +# Mesa 3-D graphics library +# Version: 7.9 +# +# Copyright (C) 2010 LunarG Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# Authors: +# Chia-I Wu + +import sys +import re +from optparse import OptionParser + +# number of dynamic entries +ABI_NUM_DYNAMIC_ENTRIES = 256 + +class ABIEntry(object): + """Represent an ABI entry.""" + + _match_c_param = re.compile( + '^(?P[\w\s*]+?)(?P\w+)(\[(?P\d+)\])?$') + + def __init__(self, cols, attrs): + self._parse(cols) + + self.slot = attrs['slot'] + self.hidden = attrs['hidden'] + self.alias = attrs['alias'] + + def c_prototype(self): + return '%s %s(%s)' % (self.c_return(), self.name, self.c_params()) + + def c_return(self): + ret = self.ret + if not ret: + ret = 'void' + + return ret + + def c_params(self): + """Return the parameter list used in the entry prototype.""" + c_params = [] + for t, n, a in self.params: + sep = '' if t.endswith('*') else ' ' + arr = '[%d]' % a if a else '' + c_params.append(t + sep + n + arr) + if not c_params: + c_params.append('void') + + return ", ".join(c_params) + + def c_args(self): + """Return the argument list used in the entry invocation.""" + c_args = [] + for t, n, a in self.params: + c_args.append(n) + + return ", ".join(c_args) + + def _parse(self, cols): + ret = cols.pop(0) + if ret == 'void': + ret = None + + name = cols.pop(0) + + params = [] + if not cols: + raise Exception(cols) + elif len(cols) == 1 and cols[0] == 'void': + pass + else: + for val in cols: + params.append(self._parse_param(val)) + + self.ret = ret + self.name = name + self.params = params + + def _parse_param(self, c_param): + m = self._match_c_param.match(c_param) + if not m: + raise Exception('unrecognized param ' + c_param) + + c_type = m.group('type').strip() + c_name = m.group('name') + c_array = m.group('array') + c_array = int(c_array) if c_array else 0 + + return (c_type, c_name, c_array) + + def __str__(self): + return self.c_prototype() + + def __cmp__(self, other): + # compare slot, alias, and then name + res = cmp(self.slot, other.slot) + if not res: + if not self.alias: + res = -1 + elif not other.alias: + res = 1 + + if not res: + res = cmp(self.name, other.name) + + return res + +def abi_parse_line(line): + cols = [col.strip() for col in line.split(',')] + + attrs = { + 'slot': -1, + 'hidden': False, + 'alias': None, + } + + # extract attributes from the first column + vals = cols[0].split(':') + while len(vals) > 1: + val = vals.pop(0) + if val.startswith('slot='): + attrs['slot'] = int(val[5:]) + elif val == 'hidden': + attrs['hidden'] = True + elif val.startswith('alias='): + attrs['alias'] = val[6:] + elif not val: + pass + else: + raise Exception('unknown attribute %s' % val) + cols[0] = vals[0] + + return (attrs, cols) + +def abi_parse(filename): + """Parse a CSV file for ABI entries.""" + fp = open(filename) if filename != '-' else sys.stdin + lines = [line.strip() for line in fp.readlines() + if not line.startswith('#') and line.strip()] + + entry_dict = {} + next_slot = 0 + for line in lines: + attrs, cols = abi_parse_line(line) + + # post-process attributes + if attrs['alias']: + try: + ent = entry_dict[attrs['alias']] + slot = ent.slot + except KeyError: + raise Exception('failed to alias %s' % attrs['alias']) + else: + slot = next_slot + next_slot += 1 + + if attrs['slot'] < 0: + attrs['slot'] = slot + elif attrs['slot'] != slot: + raise Exception('invalid slot in %s' % (line)) + + ent = ABIEntry(cols, attrs) + if entry_dict.has_key(ent.name): + raise Exception('%s is duplicated' % (ent.name)) + entry_dict[ent.name] = ent + + entries = entry_dict.values() + entries.sort() + + # sanity check + i = 0 + for slot in xrange(next_slot): + if entries[i].slot != slot: + 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)) + while i < len(entries) and entries[i].slot == slot: + i += 1 + if i < len(entries): + raise Exception('there are %d invalid entries' % (len(entries) - 1)) + + return entries + +def abi_dynamics(): + """Return the dynamic entries.""" + entries = [] + for i in xrange(ABI_NUM_DYNAMIC_ENTRIES): + cols = ['void', 'dynamic%d' % (i), 'void'] + attrs = { 'slot': -1, 'hidden': False, 'alias': None } + entries.append(ABIEntry(cols, attrs)) + return entries + +class ABIPrinter(object): + """ABIEntry Printer""" + + def __init__(self, entries, options): + self.entries = entries + self.options = options + self._undefs = [] + + def _add_undefs(self, undefs): + self._undefs.extend(undefs) + + def output_header(self): + print '/* This file is automatically generated. Do not modify. */' + print + + def output_footer(self): + print '/* clean up */' + for m in self._undefs: + print '#undef %s' % (m) + + def output_entry(self, ent): + if ent.slot < 0: + out_ent = 'MAPI_DYNAMIC_ENTRY(%s, %s, (%s))' % \ + (ent.c_return(), ent.name, ent.c_params()) + out_code = '' + else: + if ent.alias: + macro_ent = 'MAPI_ALIAS_ENTRY' + macro_code = 'MAPI_ALIAS_CODE' + else: + macro_ent = 'MAPI_ABI_ENTRY' + macro_code = 'MAPI_ABI_CODE' + + if ent.ret: + macro_code += '_RETURN' + if ent.hidden: + macro_ent += '_HIDDEN' + macro_code += '_HIDDEN' + + if ent.alias: + out_ent = '%s(%s, %s, %s, (%s))' % (macro_ent, + ent.alias, ent.c_return(), ent.name, ent.c_params()) + out_code = '%s(%s, %s, %s, (%s))' % (macro_code, + ent.alias, ent.c_return(), ent.name, ent.c_args()) + else: + out_ent = '%s(%s, %s, (%s))' % (macro_ent, + ent.c_return(), ent.name, ent.c_params()) + out_code = '%s(%s, %s, (%s))' % (macro_code, + ent.c_return(), ent.name, ent.c_args()) + + print out_ent + if out_code: + print ' ' + out_code + + def output_entries(self, pool_offsets): + defs = [ + # normal entries + ('MAPI_ABI_ENTRY', '(ret, name, params)', ''), + ('MAPI_ABI_CODE', '(ret, name, args)', ''), + ('MAPI_ABI_CODE_RETURN', '', 'MAPI_ABI_CODE'), + # alias entries + ('MAPI_ALIAS_ENTRY', '(alias, ret, name, params)', ''), + ('MAPI_ALIAS_CODE', '(alias, ret, name, args)', ''), + ('MAPI_ALIAS_CODE_RETURN', '', 'MAPI_ALIAS_CODE'), + # hidden normal entries + ('MAPI_ABI_ENTRY_HIDDEN', '', 'MAPI_ABI_ENTRY'), + ('MAPI_ABI_CODE_HIDDEN', '', 'MAPI_ABI_CODE'), + ('MAPI_ABI_CODE_RETURN_HIDDEN', '', 'MAPI_ABI_CODE_RETURN'), + # hidden alias entries + ('MAPI_ALIAS_ENTRY_HIDDEN', '', 'MAPI_ALIAS_ENTRY'), + ('MAPI_ALIAS_CODE_HIDDEN', '', 'MAPI_ALIAS_CODE'), + ('MAPI_ALIAS_CODE_RETURN_HIDDEN', '', 'MAPI_ALIAS_CODE_RETURN'), + # dynamic entries + ('MAPI_DYNAMIC_ENTRY', '(ret, name, params)', ''), + ] + undefs = [d[0] for d in defs] + + print '#if defined(MAPI_ABI_ENTRY) || defined(MAPI_ABI_ENTRY_HIDDEN)' + print + for d in defs: + print '#ifndef %s' % (d[0]) + if d[2]: + print '#define %s%s %s' % d + else: + print '#define %s%s' % d[:2] + + print '#endif' + print + + print '/* see MAPI_TMP_TABLE */' + for ent in self.entries: + print '#define MAPI_SLOT_%s %d' % (ent.name, ent.slot) + print + print '/* see MAPI_TMP_PUBLIC_STUBS */' + for ent in self.entries: + print '#define MAPI_POOL_%s %d' % (ent.name, pool_offsets[ent]) + print + + # define macros that generate code + for ent in self.entries: + self.output_entry(ent) + print + dynamics = abi_dynamics() + for ent in dynamics: + self.output_entry(ent) + print + + for ent in self.entries: + print '#undef MAPI_SLOT_%s' % (ent.name) + for ent in self.entries: + print '#undef MAPI_POOL_%s' % (ent.name) + print + print '#endif /* defined(MAPI_ABI_ENTRY) || defined(MAPI_ABI_ENTRY_HIDDEN) */' + print + + self._add_undefs(undefs) + + def _get_string_pool(self): + """Get the string pool.""" + pool = [] + offsets = {} + + count = 0 + for ent in self.entries: + offsets[ent] = count + pool.append(ent.name + '\\0') + count += len(ent.name) + 1 + + return (pool, offsets) + + def output_sorted_indices(self): + entry_index_pairs = [] + for i in xrange(len(self.entries)): + entry_index_pairs.append((self.entries[i], i)) + entry_index_pairs.sort(lambda x, y: cmp(x[0].name, y[0].name)) + + print '/* see MAPI_TMP_PUBLIC_STUBS */' + print '#ifdef MAPI_ABI_SORTED_INDICES' + print + print 'static const int MAPI_ABI_SORTED_INDICES[] = {' + for ent, idx in entry_index_pairs: + print ' %d, /* %s */' % (idx, ent.name) + print ' -1' + print '};' + print + print '#endif /* MAPI_ABI_SORTED_INDICES */' + print + + self._add_undefs(['MAPI_ABI_SORTED_INDICES']) + + def output_defines(self): + print '/* ABI defines */' + print '#ifdef MAPI_ABI_DEFINES' + print '#include "%s"' % (self.options.include) + print '#endif /* MAPI_ABI_DEFINES */' + print + + self._add_undefs(['MAPI_ABI_DEFINES']) + + def output(self): + pool, pool_offsets = self._get_string_pool() + + self.output_header() + self.output_defines() + self.output_entries(pool_offsets) + self.output_sorted_indices() + self.output_footer() + +def parse_args(): + parser = OptionParser(usage='usage: %prog [options] ') + parser.add_option('-i', '--include', dest='include', + help='include the header for API defines') + + options, args = parser.parse_args() + if not args or not options.include: + parser.print_help() + sys.exit(1) + + return (args[0], options) + +def main(): + filename, options = parse_args() + + entries = abi_parse(filename) + printer = ABIPrinter(entries, options) + printer.output() + +if __name__ == '__main__': + main() diff --git a/src/mapi/mapi/mapi_tmp.h b/src/mapi/mapi/mapi_tmp.h new file mode 100644 index 00000000000..da4e8ae54fa --- /dev/null +++ b/src/mapi/mapi/mapi_tmp.h @@ -0,0 +1,186 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include "u_macros.h" + +#ifndef MAPI_ABI_HEADER +#error "MAPI_ABI_HEADER must be defined" +#endif + + +/** + * Get API defines. + */ +#ifdef MAPI_TMP_DEFINES +# define MAPI_ABI_DEFINES +# include MAPI_ABI_HEADER + +#ifndef MAPI_ABI_PREFIX +#error "MAPI_ABI_PREFIX must be defined" +#endif +#ifndef MAPI_ABI_PUBLIC +#error "MAPI_ABI_PUBLIC must be defined" +#endif +#ifndef MAPI_ABI_ATTR +#error "MAPI_ABI_ATTR must be defined" +#endif + +#undef MAPI_TMP_DEFINES +#endif /* MAPI_TMP_DEFINES */ + + +/** + * Generate fields of struct mapi_table. + */ +#ifdef MAPI_TMP_TABLE +# define MAPI_ABI_ENTRY(ret, name, params) \ + ret (MAPI_ABI_ATTR *name) params; +# define MAPI_DYNAMIC_ENTRY(ret, name, params) \ + ret (MAPI_ABI_ATTR *name) params; +# include MAPI_ABI_HEADER +#undef MAPI_TMP_TABLE +#endif /* MAPI_TMP_TABLE */ + + +/** + * Declare public entries. + */ +#ifdef MAPI_TMP_PUBLIC_DECLARES +# define MAPI_ABI_ENTRY(ret, name, params) \ + MAPI_ABI_PUBLIC ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params; +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params); +# define MAPI_ABI_ENTRY_HIDDEN(ret, name, params) \ + HIDDEN ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params; +# define MAPI_ALIAS_ENTRY_HIDDEN(alias, ret, name, params) \ + MAPI_ABI_ENTRY_HIDDEN(ret, name, params) +# include MAPI_ABI_HEADER +#undef MAPI_TMP_PUBLIC_DECLARES +#endif /* MAPI_TMP_PUBLIC_DECLARES */ + + +/** + * Generate string pool and public stubs. + */ +#ifdef MAPI_TMP_PUBLIC_STUBS +/* define the string pool */ +static const char public_string_pool[] = +# define MAPI_ABI_ENTRY(ret, name, params) \ + U_STRINGIFY(name) "\0" +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params) +# include MAPI_ABI_HEADER + ; +/* define public_sorted_indices */ +# define MAPI_ABI_SORTED_INDICES public_sorted_indices +# include MAPI_ABI_HEADER + +/* define public_stubs */ +static const struct mapi_stub public_stubs[] = { +# define MAPI_ABI_ENTRY(ret, name, params) \ + { (mapi_func) U_CONCAT(MAPI_ABI_PREFIX, name), \ + MAPI_SLOT_ ## name, (void *) MAPI_POOL_ ## name }, +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params) +# include MAPI_ABI_HEADER + { NULL, -1, (void *) -1 } +}; + +#undef MAPI_TMP_PUBLIC_STUBS +#endif /* MAPI_TMP_PUBLIC_STUBS */ + + +/** + * Generate public entries. + */ +#ifdef MAPI_TMP_PUBLIC_ENTRIES +# define MAPI_ABI_ENTRY(ret, name, params) \ + ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params +# define MAPI_ABI_CODE(ret, name, args) \ + { \ + const struct mapi_table *tbl = u_current_get(); \ + tbl->name args; \ + } +# define MAPI_ABI_CODE_RETURN(ret, name, args) \ + { \ + const struct mapi_table *tbl = u_current_get(); \ + return tbl->name args; \ + } +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params) +# define MAPI_ALIAS_CODE(alias, ret, name, args) \ + MAPI_ABI_CODE(ret, alias, args) +# define MAPI_ALIAS_CODE_RETURN(alias, ret, name, args) \ + MAPI_ABI_CODE_RETURN(ret, alias, args) +# include MAPI_ABI_HEADER +#undef MAPI_TMP_PUBLIC_ENTRIES +#endif /* MAPI_TMP_PUBLIC_ENTRIES */ + + +/** + * Generate noop entries. + */ +#ifdef MAPI_TMP_NOOP_ARRAY +#ifdef DEBUG +# define MAPI_ABI_ENTRY(ret, name, params) \ + static ret MAPI_ABI_ATTR U_CONCAT(noop_, name) params +# define MAPI_ABI_CODE(ret, name, args) \ + { \ + noop_warn(U_CONCAT_STR(MAPI_ABI_PREFIX, name)); \ + } +# define MAPI_ABI_CODE_RETURN(ret, name, args) \ + { \ + noop_warn(U_CONCAT_STR(MAPI_ABI_PREFIX, name)); \ + return (ret) 0; \ + } +# include MAPI_ABI_HEADER + +/* define the noop function array that may be casted to mapi_table */ +const mapi_func table_noop_array[] = { +# define MAPI_ABI_ENTRY(ret, name, params) \ + (mapi_func) U_CONCAT(noop_, name), +# define MAPI_DYNAMIC_ENTRY(ret, name, params) \ + (mapi_func) noop_generic, +# include MAPI_ABI_HEADER + (mapi_func) noop_generic +}; + +#else /* DEBUG */ + +const mapi_func table_noop_array[] = { +# define MAPI_ABI_ENTRY(ret, name, params) \ + (mapi_func) noop_generic, +# define MAPI_DYNAMIC_ENTRY(ret, name, params) \ + (mapi_func) noop_generic, +# include MAPI_ABI_HEADER + (mapi_func) noop_generic +}; + +#endif /* DEBUG */ +#undef MAPI_TMP_NOOP_ARRAY +#endif /* MAPI_TMP_NOOP_ARRAY */ diff --git a/src/mapi/mapi/sources.mak b/src/mapi/mapi/sources.mak index 9e27f45e2a9..5f327f3df62 100644 --- a/src/mapi/mapi/sources.mak +++ b/src/mapi/mapi/sources.mak @@ -1,6 +1,19 @@ # src/mapi/mapi/sources.mak +# +# When MAPI_GLAPI_CURRENT is defined, MAPI_GLAPI_SOURCES can be built without +# MAPI_SOURCES and it is used by glapi. +# +# Otherwise, MAPI_ABI_HEADER must be defined. It should expand to the header +# generated by mapi_abi.py. MAPI_GLAPI_SOURCES = \ u_current.c \ u_execmem.c \ u_thread.c + +MAPI_SOURCES = \ + entry.c \ + mapi.c \ + stub.c \ + table.c \ + $(MAPI_GLAPI_SOURCES) diff --git a/src/mapi/mapi/stub.c b/src/mapi/mapi/stub.c new file mode 100644 index 00000000000..8ceaec3132b --- /dev/null +++ b/src/mapi/mapi/stub.c @@ -0,0 +1,180 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include +#include /* for offsetof */ +#include +#include + +#include "u_current.h" +#include "u_thread.h" +#include "entry.h" +#include "stub.h" +#include "table.h" + +#define MAPI_TABLE_FIRST_DYNAMIC \ + (offsetof(struct mapi_table, dynamic0) / sizeof(mapi_func)) +#define MAPI_TABLE_NUM_DYNAMIC \ + ((offsetof(struct mapi_table, last) - \ + offsetof(struct mapi_table, dynamic0)) / sizeof(mapi_func)) +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +/* + * This will define public_string_pool, public_sorted_indices, and + * public_stubs. + */ +#define MAPI_TMP_PUBLIC_STUBS +#include "mapi_tmp.h" + +static struct mapi_stub dynamic_stubs[MAPI_TABLE_NUM_DYNAMIC]; +static int num_dynamic_stubs; +static int next_dynamic_slot = MAPI_TABLE_FIRST_DYNAMIC; + +void +stub_init_once(void) +{ +#ifdef PTHREADS + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, entry_patch_public); +#else + static int first = 1; + if (first) { + first = 0; + entry_patch_public(); + } +#endif +} + +static int +stub_compare(const void *key, const void *elem) +{ + const char *name = (const char *) key; + const int *index = (const int *) elem; + const struct mapi_stub *stub; + const char *stub_name; + + stub = &public_stubs[*index]; + stub_name = &public_string_pool[(unsigned long) stub->name]; + + return strcmp(name, stub_name); +} + +/** + * Return the public stub with the given name. + */ +const struct mapi_stub * +stub_find_public(const char *name) +{ + const int *index; + + index = (const int *) bsearch(name, public_sorted_indices, + ARRAY_SIZE(public_sorted_indices) - 1, + sizeof(public_sorted_indices[0]), stub_compare); + + return (index) ? &public_stubs[*index] : NULL; +} + +/** + * Add a dynamic stub. + */ +static struct mapi_stub * +stub_add_dynamic(const char *name) +{ + struct mapi_stub *stub; + int idx; + + idx = num_dynamic_stubs; + if (idx >= MAPI_TABLE_NUM_DYNAMIC) + return NULL; + + stub = &dynamic_stubs[idx]; + + /* dispatch to mapi_table->last, which is always no-op */ + stub->addr = + entry_generate(MAPI_TABLE_FIRST_DYNAMIC + MAPI_TABLE_NUM_DYNAMIC); + if (!stub->addr) + return NULL; + + stub->name = (const void *) name; + /* to be fixed later */ + stub->slot = -1; + + num_dynamic_stubs = idx + 1; + + return stub; +} + +/** + * Return the dynamic stub with the given name. If no such stub exists and + * generate is true, a new stub is generated. + */ +struct mapi_stub * +stub_find_dynamic(const char *name, int generate) +{ + u_mutex_declare_static(dynamic_mutex); + struct mapi_stub *stub = NULL; + int count, i; + + u_mutex_lock(dynamic_mutex); + + if (generate) + assert(!stub_find_public(name)); + + count = num_dynamic_stubs; + for (i = 0; i < count; i++) { + if (strcmp(name, (const char *) dynamic_stubs[i].name) == 0) { + stub = &dynamic_stubs[i]; + break; + } + } + + /* generate a dynamic stub */ + if (generate && !stub) + stub = stub_add_dynamic(name); + + u_mutex_unlock(dynamic_mutex); + + return stub; +} + +void +stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias) +{ + int slot; + + if (stub->slot >= 0) + return; + + if (alias) + slot = alias->slot; + else + slot = next_dynamic_slot++; + + entry_patch(stub->addr, slot); + stub->slot = slot; +} diff --git a/src/mapi/mapi/stub.h b/src/mapi/mapi/stub.h new file mode 100644 index 00000000000..c7e194cf4fc --- /dev/null +++ b/src/mapi/mapi/stub.h @@ -0,0 +1,52 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef _STUB_H_ +#define _STUB_H_ + +typedef void (*mapi_func)(void); + +struct mapi_stub { + mapi_func addr; + int slot; + const void *name; +}; + +void +stub_init_once(void); + +const struct mapi_stub * +stub_find_public(const char *name); + +struct mapi_stub * +stub_find_dynamic(const char *name, int generate); + +void +stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias); + +#endif /* _STUB_H_ */ diff --git a/src/mapi/mapi/table.c b/src/mapi/mapi/table.c new file mode 100644 index 00000000000..8f4f700b920 --- /dev/null +++ b/src/mapi/mapi/table.c @@ -0,0 +1,56 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#include +#include + +#include "stub.h" +#include "table.h" + +static void +noop_warn(const char *name) +{ + static int debug = -1; + + if (debug < 0) + debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")); + + if (debug) + fprintf(stderr, "%s is no-op", name); +} + +static int +noop_generic(void) +{ + noop_warn("function"); + return 0; +} + +/* define noop_array */ +#define MAPI_TMP_NOOP_ARRAY +#include "mapi_tmp.h" diff --git a/src/mapi/mapi/table.h b/src/mapi/mapi/table.h new file mode 100644 index 00000000000..48c99018aa3 --- /dev/null +++ b/src/mapi/mapi/table.h @@ -0,0 +1,76 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu + */ + +#ifndef _TABLE_H_ +#define _TABLE_H_ + +#include "u_compiler.h" +#include "stub.h" + +#define MAPI_TMP_DEFINES +#include "mapi_tmp.h" + +struct mapi_table { +#define MAPI_TMP_TABLE +#include "mapi_tmp.h" + mapi_func last; +}; + +extern const mapi_func table_noop_array[]; + +/** + * Get the no-op dispatch table. + */ +static INLINE const struct mapi_table * +table_get_noop(void) +{ + return (const struct mapi_table *) table_noop_array; +} + +/** + * Update the dispatch table to dispatch a stub to the given function. + */ +static INLINE void +table_set_func(struct mapi_table *tbl, + const struct mapi_stub *stub, mapi_func func) +{ + mapi_func *funcs = (mapi_func *) tbl; + funcs[stub->slot] = func; +} + +/** + * Return the dispatched function of a stub. + */ +static INLINE mapi_func +table_get_func(const struct mapi_table *tbl, const struct mapi_stub *stub) +{ + const mapi_func *funcs = (const mapi_func *) tbl; + return funcs[stub->slot]; +} + +#endif /* _TABLE_H_ */ diff --git a/src/mapi/mapi/u_macros.h b/src/mapi/mapi/u_macros.h new file mode 100644 index 00000000000..72345b5f156 --- /dev/null +++ b/src/mapi/mapi/u_macros.h @@ -0,0 +1,12 @@ +#ifndef _U_MACROS_ +#define _U_MACROS_ + +#define _U_STRINGIFY(x) #x +#define _U_CONCAT(x, y) x ## y +#define _U_CONCAT_STR(x, y) #x#y + +#define U_STRINGIFY(x) _U_STRINGIFY(x) +#define U_CONCAT(x, y) _U_CONCAT(x, y) +#define U_CONCAT_STR(x, y) _U_CONCAT_STR(x, y) + +#endif /* _U_MACROS_ */ -- 2.30.2