+ # Process all introduced methods and compile some linking information (if needed)
+ fun link_mmethods
+ do
+ if not modelbuilder.toolcontext.opt_substitute_monomorph.value and not modelbuilder.toolcontext.opt_guard_call.value then return
+
+ for mmodule in mainmodule.in_importation.greaters do
+ for cd in mmodule.mclassdefs do
+ for m in cd.intro_mproperties do
+ if not m isa MMethod then continue
+ link_mmethod(m)
+ end
+ end
+ end
+ end
+
+ # Compile some linking information (if needed)
+ fun link_mmethod(m: MMethod)
+ do
+ var n2 = "CALL_" + m.const_color
+
+ # Replace monomorphic call by a direct call to the virtual implementation
+ var md = is_monomorphic(m)
+ if md != null then
+ linker_script.add("{n2} = {md.virtual_runtime_function.c_name};")
+ end
+
+ # If opt_substitute_monomorph then a trampoline is used, else a weak symbol is used
+ if modelbuilder.toolcontext.opt_guard_call.value then
+ var r = m.intro.virtual_runtime_function
+ provide_declaration(n2, "{r.c_ret} {n2}{r.c_sig} __attribute__((weak));")
+ end
+ end
+
+ # The single mmethodef called in case of monomorphism.
+ # Returns nul if dead or polymorphic.
+ fun is_monomorphic(m: MMethod): nullable MMethodDef
+ do
+ var rta = runtime_type_analysis
+ if rta == null then
+ # Without RTA, monomorphic means alone (uniq name)
+ if m.mpropdefs.length == 1 then
+ return m.mpropdefs.first
+ else
+ return null
+ end
+ else
+ # With RTA, monomorphic means only live methoddef
+ var res: nullable MMethodDef = null
+ for md in m.mpropdefs do
+ if rta.live_methoddefs.has(md) then
+ if res != null then return null
+ res = md
+ end
+ end
+ return res
+ end
+ end
+