Example #1
0
        /// <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);
        }
Example #2
0
        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();
        }