Skip to content

Commit 9824cfc

Browse files
committed
Document export tables a bunch more and rename get_lib_prefix -> get_group_prefix
1 parent bef450e commit 9824cfc

File tree

5 files changed

+41
-14
lines changed

5 files changed

+41
-14
lines changed

mypyc/emit.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ def new_label(self) -> str:
145145
self.context.temp_counter += 1
146146
return '__LL%d' % self.context.temp_counter
147147

148-
def get_module_lib_prefix(self, module_name: str) -> str:
149-
"""Get the library prefix for a module.
148+
def get_module_group_prefix(self, module_name: str) -> str:
149+
"""Get the group prefix for a module (relative to the current group).
150150
151151
The prefix should be prepended to the object name whenever
152152
accessing an object from this module.
@@ -155,6 +155,13 @@ def get_module_lib_prefix(self, module_name: str) -> str:
155155
no prefix. But if it lives in a different group (and hence a separate
156156
extension module), we need to access objects from it indirectly via an
157157
export table.
158+
159+
For example, for code in group `a` to call a function `bar` in group `b`,
160+
it would need to do `exports_b.CPyDef_bar(...)`, while code that is
161+
also in group `b` can simply do `CPyDef_bar(...)`.
162+
163+
Thus the prefix for a module in group `b` is 'exports_b.' if the current
164+
group is *not* b and just '' if it is.
158165
"""
159166
groups = self.context.group_map
160167
target_group_name = groups.get(module_name)
@@ -164,10 +171,10 @@ def get_module_lib_prefix(self, module_name: str) -> str:
164171
else:
165172
return ''
166173

167-
def get_lib_prefix(self, obj: Union[ClassIR, FuncDecl]) -> str:
168-
"""Get the library prefix for an object."""
174+
def get_group_prefix(self, obj: Union[ClassIR, FuncDecl]) -> str:
175+
"""Get the group prefix for an object."""
169176
# See docs above
170-
return self.get_module_lib_prefix(obj.module_name)
177+
return self.get_module_group_prefix(obj.module_name)
171178

172179
def static_name(self, id: str, module: Optional[str], prefix: str = STATIC_PREFIX) -> str:
173180
"""Create name of a C static variable.
@@ -179,7 +186,7 @@ def static_name(self, id: str, module: Optional[str], prefix: str = STATIC_PREFI
179186
overlap with other calls to this method within a compilation
180187
group.
181188
"""
182-
lib_prefix = '' if not module else self.get_module_lib_prefix(module)
189+
lib_prefix = '' if not module else self.get_module_group_prefix(module)
183190
# If we are accessing static via the export table, we need to dereference
184191
# the pointer also.
185192
star_maybe = '*' if lib_prefix else ''

mypyc/emitclass.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,14 +397,14 @@ def generate_vtable(entries: VTableEntries,
397397
for entry in entries:
398398
if isinstance(entry, VTableMethod):
399399
emitter.emit_line('(CPyVTableItem){}{}{},'.format(
400-
emitter.get_lib_prefix(entry.method.decl),
400+
emitter.get_group_prefix(entry.method.decl),
401401
NATIVE_PREFIX,
402402
entry.method.cname(emitter.names)))
403403
else:
404404
cl, attr, is_setter = entry
405405
namer = native_setter_name if is_setter else native_getter_name
406406
emitter.emit_line('(CPyVTableItem){}{},'.format(
407-
emitter.get_lib_prefix(cl),
407+
emitter.get_group_prefix(cl),
408408
namer(cl, attr, emitter.names)))
409409
# msvc doesn't allow empty arrays; maybe allowing them at all is an extension?
410410
if not entries:
@@ -462,7 +462,7 @@ def generate_constructor_for_class(cl: ClassIR,
462462
args = ', '.join(['self'] + [REG_PREFIX + arg.name for arg in fn.sig.args])
463463
if init_fn is not None:
464464
emitter.emit_line('char res = {}{}{}({});'.format(
465-
emitter.get_lib_prefix(init_fn.decl),
465+
emitter.get_group_prefix(init_fn.decl),
466466
NATIVE_PREFIX, init_fn.cname(emitter.names), args))
467467
emitter.emit_line('if (res == 2) {')
468468
emitter.emit_line('Py_DECREF(self);')

mypyc/emitfunc.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ def visit_get_attr(self, op: GetAttr) -> None:
224224
# duplicating getter/setter code.
225225
self.emit_line('%s = %s%s((%s *)%s); /* %s */' % (
226226
dest,
227-
self.emitter.get_lib_prefix(decl_cl),
227+
self.emitter.get_group_prefix(decl_cl),
228228
native_getter_name(decl_cl, op.attr, self.emitter.names),
229229
decl_cl.struct_name(self.names),
230230
obj,
@@ -252,7 +252,7 @@ def visit_set_attr(self, op: SetAttr) -> None:
252252
typ, decl_cl = cl.attr_details(op.attr)
253253
self.emit_line('%s = %s%s((%s *)%s, %s); /* %s */' % (
254254
dest,
255-
self.emitter.get_lib_prefix(decl_cl),
255+
self.emitter.get_group_prefix(decl_cl),
256256
native_setter_name(decl_cl, op.attr, self.emitter.names),
257257
decl_cl.struct_name(self.names),
258258
obj,
@@ -303,7 +303,7 @@ def visit_call(self, op: Call) -> None:
303303
"""Call native function."""
304304
dest = self.get_dest_assign(op)
305305
args = ', '.join(self.reg(arg) for arg in op.args)
306-
lib = self.emitter.get_lib_prefix(op.fn)
306+
lib = self.emitter.get_group_prefix(op.fn)
307307
cname = op.fn.cname(self.names)
308308
self.emit_line('%s%s%s%s(%s);' % (dest, lib, NATIVE_PREFIX, cname, args))
309309

@@ -333,7 +333,7 @@ def visit_method_call(self, op: MethodCall) -> None:
333333
version = '_TRAIT' if rtype.class_ir.is_trait else ''
334334
if is_direct:
335335
# Directly call method, without going through the vtable.
336-
lib = self.emitter.get_lib_prefix(method.decl)
336+
lib = self.emitter.get_group_prefix(method.decl)
337337
self.emit_line('{}{}{}{}({});'.format(
338338
dest, lib, NATIVE_PREFIX, method.cname(self.names), args))
339339
else:

mypyc/emitmodule.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,26 @@ def generate_export_table(self, decl_emitter: Emitter, code_emitter: Emitter) ->
363363
364364
Then, all calls to functions in another group and accesses to statics
365365
from another group are done indirectly via the export table.
366+
367+
For example, a group containing a module b, where b contains a class B
368+
and a function bar, would declare an export table like:
369+
struct export_table_b {
370+
PyTypeObject **CPyType_B;
371+
PyObject *(*CPyDef_B)(CPyTagged cpy_r_x);
372+
CPyTagged (*CPyDef_B___foo)(PyObject *cpy_r_self, CPyTagged cpy_r_y);
373+
tuple_T2OI (*CPyDef_bar)(PyObject *cpy_r_x);
374+
char (*CPyDef___top_level__)(void);
375+
};
376+
that would be initialized with:
377+
static struct export_table_b exports = {
378+
&CPyType_B,
379+
&CPyDef_B,
380+
&CPyDef_B___foo,
381+
&CPyDef_bar,
382+
&CPyDef___top_level__,
383+
};
384+
To call `b.foo`, then, a function in another group would do
385+
`exports_b.CPyDef_bar(...)`.
366386
"""
367387

368388
decls = decl_emitter.context.declarations

mypyc/emitwrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ def generate_hash_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:
176176
name=name
177177
))
178178
emitter.emit_line('{}retval = {}{}{}(self);'.format(emitter.ctype_spaced(fn.ret_type),
179-
emitter.get_lib_prefix(fn.decl),
179+
emitter.get_group_prefix(fn.decl),
180180
NATIVE_PREFIX,
181181
fn.cname(emitter.names)))
182182
emitter.emit_error_check('retval', fn.ret_type, 'return -1;')

0 commit comments

Comments
 (0)