var r = pd.separate_runtime_function
r.compile_to_c(self)
var r2 = pd.virtual_runtime_function
- r2.compile_to_c(self)
+ if r2 != r then r2.compile_to_c(self)
end
end
self.mainmodule = old_module
var res0 = before_send(mmethod, arguments)
+ var runtime_function = mmethod.intro.virtual_runtime_function
+ var msignature = runtime_function.called_signature
+
var res: nullable RuntimeVariable
- var msignature = mmethod.intro.msignature.resolve_for(mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.mmodule, true)
var ret = msignature.return_mtype
if ret == null then
res = null
res = self.new_var(ret)
end
- var s = new FlatBuffer
var ss = new FlatBuffer
- s.append("val*")
ss.append("{recv}")
for i in [0..msignature.arity[ do
var a = arguments[i+1]
if i == msignature.vararg_rank then
t = arguments[i+1].mcasttype
end
- s.append(", {t.ctype}")
a = self.autobox(a, t)
ss.append(", {a}")
end
-
- var r
- if ret == null then r = "void" else r = ret.ctype
self.require_declaration(const_color)
- var call = "(({r} (*)({s}))({arguments.first}->class->vft[{const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
+ var call = "(({runtime_function.c_ret} (*){runtime_function.c_sig})({arguments.first}->class->vft[{const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
if res != null then
self.add("{res} = {call};")
# Because the function is virtual, the signature must match the one of the original class
var intromclassdef = mproperty.intro.mclassdef
var recv = intromclassdef.bound_mtype
+
+ res = separate_runtime_function
+ if res.called_recv == recv then
+ self.virtual_runtime_function_cache = res
+ return res
+ end
+
var msignature = mproperty.intro.msignature.resolve_for(recv, recv, intromclassdef.mmodule, true)
+
+ if recv.ctype == res.called_recv.ctype and msignature.c_equiv(res.called_signature) then
+ self.virtual_runtime_function_cache = res
+ return res
+ end
+
res = new SeparateRuntimeFunction(self, recv, msignature, "VIRTUAL_{c_name}")
self.virtual_runtime_function_cache = res
res.is_thunk = true
private var virtual_runtime_function_cache: nullable SeparateRuntimeFunction
end
+redef class MSignature
+ # Does the C-version of `self` the same than the C-version of `other`?
+ fun c_equiv(other: MSignature): Bool
+ do
+ if self == other then return true
+ if arity != other.arity then return false
+ for i in [0..arity[ do
+ if mparameters[i].mtype.ctype != other.mparameters[i].mtype.ctype then return false
+ end
+ if return_mtype != other.return_mtype then
+ if return_mtype == null or other.return_mtype == null then return false
+ if return_mtype.ctype != other.return_mtype.ctype then return false
+ end
+ return true
+ end
+end
+
# The C function associated to a methoddef separately compiled
class SeparateRuntimeFunction
super AbstractRuntimeFunction
redef fun to_s do return self.mmethoddef.to_s
+ # The C return type (something or `void`)
+ var c_ret: String is lazy do
+ var ret = called_signature.return_mtype
+ if ret != null then
+ return ret.ctype
+ else
+ return "void"
+ end
+ end
+
+ # The C signature (only the parmeter part)
+ var c_sig: String is lazy do
+ var sig = new FlatBuffer
+ sig.append("({called_recv.ctype} self")
+ for i in [0..called_signature.arity[ do
+ var mtype = called_signature.mparameters[i].mtype
+ if i == called_signature.vararg_rank then
+ mtype = mmethoddef.mclassdef.mmodule.get_primitive_class("Array").get_mtype([mtype])
+ end
+ sig.append(", {mtype.ctype} p{i}")
+ end
+ sig.append(")")
+ return sig.to_s
+ end
+
redef fun compile_to_c(compiler)
do
var mmethoddef = self.mmethoddef
v.frame = frame
var msignature = called_signature
+ var ret = called_signature.return_mtype
var sig = new FlatBuffer
var comment = new FlatBuffer
- var ret = msignature.return_mtype
- if ret != null then
- sig.append("{ret.ctype} ")
- else
- sig.append("void ")
- end
+ sig.append(c_ret)
+ sig.append(" ")
sig.append(self.c_name)
- sig.append("({selfvar.mtype.ctype} {selfvar}")
+ sig.append(c_sig)
comment.append("({selfvar}: {selfvar.mtype}")
arguments.add(selfvar)
for i in [0..msignature.arity[ do
mtype = v.get_class("Array").get_mtype([mtype])
end
comment.append(", {mtype}")
- sig.append(", {mtype.ctype} p{i}")
var argvar = new RuntimeVariable("p{i}", mtype, mtype)
arguments.add(argvar)
end
- sig.append(")")
comment.append(")")
if ret != null then
comment.append(": {ret}")