MCPcopy
hub / github.com/python/mypy / generate_native_function

Function generate_native_function

mypyc/codegen/emitfunc.py:124–200  ·  view source on GitHub ↗
(
    fn: FuncIR, emitter: Emitter, source_path: str, module_name: str
)

Source from the content-addressed store, hash-verified

122
123
124def generate_native_function(
125 fn: FuncIR, emitter: Emitter, source_path: str, module_name: str
126) -> None:
127 declarations = Emitter(emitter.context)
128 names = generate_names_for_ir(fn.arg_regs, fn.blocks)
129 body = Emitter(emitter.context, names)
130 visitor = FunctionEmitterVisitor(body, declarations, source_path, module_name)
131
132 declarations.emit_line(f"{native_function_header(fn.decl, emitter)} {{")
133 body.indent()
134
135 for r in all_values(fn.arg_regs, fn.blocks):
136 if isinstance(r.type, RTuple):
137 emitter.declare_tuple_struct(r.type)
138 if isinstance(r.type, RArray):
139 continue # Special: declared on first assignment
140
141 if r in fn.arg_regs:
142 continue # Skip the arguments
143
144 ctype = emitter.ctype_spaced(r.type)
145 init = ""
146 declarations.emit_line(
147 "{ctype}{prefix}{name}{init};".format(
148 ctype=ctype, prefix=REG_PREFIX, name=names[r], init=init
149 )
150 )
151
152 # Before we emit the blocks, give them all labels
153 blocks = fn.blocks
154 for i, block in enumerate(blocks):
155 block.label = i
156
157 # Find blocks that are never jumped to or are only jumped to from the
158 # block directly above it. This allows for more labels and gotos to be
159 # eliminated during code generation.
160 for block in fn.blocks:
161 terminator = block.terminator
162 assert isinstance(terminator, ControlOp), terminator
163
164 for target in terminator.targets():
165 is_next_block = target.label == block.label + 1
166
167 # Always emit labels for GetAttr error checks since the emit code that
168 # generates them will add instructions between the branch and the
169 # next label, causing the label to be wrongly removed. A better
170 # solution would be to change the IR so that it adds a basic block
171 # in between the calls.
172 is_problematic_op = isinstance(terminator, Branch) and any(
173 isinstance(s, GetAttr) for s in terminator.sources()
174 )
175
176 if not is_next_block or is_problematic_op:
177 fn.blocks[target.label].referenced = True
178
179 common = frequently_executed_blocks(fn.blocks[0])
180
181 for i in range(len(blocks)):

Callers 3

test_simpleMethod · 0.90
test_registerMethod · 0.90

Calls 15

emit_lineMethod · 0.95
indentMethod · 0.95
emit_labelMethod · 0.95
EmitterClass · 0.90
generate_names_for_irFunction · 0.90
all_valuesFunction · 0.90
native_function_headerFunction · 0.85
isinstanceFunction · 0.85
enumerateFunction · 0.85
anyFunction · 0.85

Tested by 2

test_simpleMethod · 0.72
test_registerMethod · 0.72

Used in the wild real call sites across dependent graphs

searching dependent graphs…