/// <summary> /// Retrieves the linkage for a local user method call. /// A local user method call means any method that is not a call on a different Udon Behaviour. /// This includes any static function call, function call on an imported user type, or call on the local UdonSharpBehaviour /// </summary> /// <param name="methodSymbol">The method symbol to get the linkage for</param> /// <param name="useVirtual">Whether this is a virtual call where we want the most derived method to be called</param> /// <returns></returns> public MethodLinkage GetMethodLinkage(MethodSymbol methodSymbol, bool useVirtual) { if (!useVirtual && _linkages.TryGetValue(methodSymbol, out var linkage)) { return(linkage); } MethodSymbol derivedMethod = GetMostDerivedMethod(methodSymbol); if (useVirtual && _linkages.TryGetValue(derivedMethod, out linkage)) { return(linkage); } MethodLinkage newLinkage; JumpLabel methodLabel = Module.CreateLabel(); Value[] parameterValues = new Value[methodSymbol.Parameters.Length]; if ((useVirtual || derivedMethod == methodSymbol) && !methodSymbol.IsStatic && methodSymbol is UdonSharpBehaviourMethodSymbol) { methodLabel.DebugMethod = derivedMethod; CompilationContext.MethodExportLayout layout = CompileContext.GetUsbMethodLayout(methodSymbol, this); Value returnValue = layout.ReturnExportName == null ? null : Module.RootTable.CreateParameterValue(layout.ReturnExportName, derivedMethod.ReturnType); for (int i = 0; i < parameterValues.Length; ++i) { parameterValues[i] = Module.RootTable.CreateParameterValue(layout.ParameterExportNames[i], methodSymbol.Parameters[i].Type); } newLinkage = new MethodLinkage(methodLabel, layout.ExportMethodName, returnValue, parameterValues); _linkages.Add(derivedMethod, newLinkage); } else { methodLabel.DebugMethod = methodSymbol; Value returnValue = methodSymbol.ReturnType == null ? null : Module.RootTable.CreateParameterValue(GetInternalParamName(), methodSymbol.ReturnType); for (int i = 0; i < parameterValues.Length; ++i) { parameterValues[i] = Module.RootTable.CreateParameterValue(GetInternalParamName(), methodSymbol.Parameters[i].Type); } newLinkage = new MethodLinkage(methodLabel, null, returnValue, parameterValues); _linkages.Add(methodSymbol, newLinkage); } return(newLinkage); }
public void EmitReturn(BoundExpression returnExpression) { if (returnExpression == null) { EmitReturn(); return; } MethodLinkage currentMethodLinkage = GetMethodLinkage(CurrentEmitMethod, false); if (currentMethodLinkage.ReturnValue != null) { EmitValueAssignment(currentMethodLinkage.ReturnValue, returnExpression); if (CurrentEmitMethod.Name == "OnOwnershipRequest" && !CurrentEmitMethod.IsExtern && GetMostDerivedMethod(CurrentEmitMethod) == CurrentEmitMethod) { if (_udonReturnValue == null) { _udonReturnValue = RootTable.CreateParameterValue("__returnValue", GetTypeSymbol(SpecialType.System_Object)); } Module.AddCopy(currentMethodLinkage.ReturnValue, _udonReturnValue); } } else { Emit(returnExpression); } EmitReturn(); }