/// <inheritdoc/>
        public bool TryGetFunctionVariant(Function function, out ImplementedFunction overload, Project core)
        {
            if (!IsApplicable(function))
            {
                overload = null;
                return(false);
            }

            var arrayParameter     = function.Parameters.Last();
            var arrayParameterType = arrayParameter.Type;

            var newName       = function.Name.Singularize(false);
            var newParameters = SkipLastExtension.SkipLast(new List <Parameter>(function.Parameters), 2).ToList();

            var newArrayParameterType = new TypeSignatureBuilder(arrayParameterType)
                                        .WithArrayDimensions(0)
                                        .WithIndirectionLevel(0)
                                        .Build();

            var newArrayParameter = new ParameterSignatureBuilder(arrayParameter)
                                    .WithType(newArrayParameterType)
                                    .Build();

            newParameters.Add(newArrayParameter);

            var sb = new StringBuilder();

            sb.AppendLine("// ArrayParameterOverloader");
            sb.AppendLine($"{function.Name}(1, &{newArrayParameter.Name});");

            overload = new ImplementedFunction(new FunctionSignatureBuilder(function)
                                               .WithName(newName)
                                               .WithParameters(newParameters)
                                               .Build(), sb, function, true);
            return(true);
        }
예제 #2
0
        public bool TryGetFunctionVariant(Function original, out ImplementedFunction varied, Project core)
        {
            varied = null;

            // use the ref overload for simplicity
            if (original.Kind != SignatureKind.SimpleOverload)
            {
                return(false);
            }

            var applicable           = false;
            var invocationParameters = new List <string>();
            var parameters           = new List <Parameter>(original.Parameters);

            for (var i = 0; i < original.Parameters.Count; i++)
            {
                var parameter = original.Parameters[i];
                var name      = (Utilities.CSharpKeywords.Contains(parameter.Name)
                    ? "@"
                    : string.Empty) + parameter.Name;
                if (parameter.Type.IsIn && !parameter.Type.IsPointer)
                {
                    applicable    = true;
                    parameters[i] = new ParameterSignatureBuilder(parameter).WithType
                                    (
                        new Type
                    {
                        Name         = "ReadOnlySpan",
                        GenericTypes = new List <Type>
                        {
                            new TypeSignatureBuilder(parameter.Type).WithIsIn(false).Build()
                        },
                        IsGenericTypeParameterReference = parameter.Type.IsGenericTypeParameterReference,
                        OriginalName = parameter.Type.OriginalName
                    }
                                    )
                                    .Build();
                    invocationParameters.Add($"in {name}.GetPinnableReference()");
                }
                else if (parameter.Type.IsOut && !parameter.Type.IsPointer)
                {
                    applicable    = true;
                    parameters[i] = new ParameterSignatureBuilder(parameter).WithType
                                    (
                        new Type
                    {
                        Name         = "Span",
                        GenericTypes = new List <Type>
                        {
                            new TypeSignatureBuilder(parameter.Type).WithIsOut(false).Build()
                        },
                        IsGenericTypeParameterReference = parameter.Type.IsGenericTypeParameterReference,
                        OriginalName = parameter.Type.OriginalName
                    }
                                    )
                                    .Build();
                    invocationParameters.Add($"out {name}.GetPinnableReference()");
                }
                else if (parameter.Type.IsByRef && !parameter.Type.IsPointer)
                {
                    applicable    = true;
                    parameters[i] = new ParameterSignatureBuilder(parameter).WithType
                                    (
                        new Type
                    {
                        Name         = "Span",
                        GenericTypes = new List <Type>
                        {
                            new TypeSignatureBuilder(parameter.Type).WithByRef(false).Build()
                        },
                        IsGenericTypeParameterReference = parameter.Type.IsGenericTypeParameterReference,
                        OriginalName = parameter.Type.OriginalName
                    }
                                    )
                                    .Build();
                    invocationParameters.Add($"ref {name}.GetPinnableReference()");
                }
                else
                {
                    invocationParameters.Add
                    (
                        (parameter.Type.IsIn ? "in " :
                         parameter.Type.IsOut ? "out " :
                         parameter.Type.IsByRef ? "ref " : string.Empty) + name
                    );
                }
            }

            if (applicable)
            {
                var sb = new StringBuilder();
                sb.AppendLine("// SpanOverloader");
                if (original.ReturnType.ToString() != "void")
                {
                    sb.Append("return ");
                }

                sb.Append("thisApi." + original.Name);
                sb.Append("(");
                sb.Append(string.Join(", ", invocationParameters));
                sb.Append(");");
                varied = new ImplementedFunction
                         (
                    new FunctionSignatureBuilder(original)
                    .WithParameters(parameters)
                    .WithKind(SignatureKind.PotentiallyConflictingOverload)
                    .Build(), sb, original
                         );
            }

            return(applicable);
        }
예제 #3
0
 static bool CheckDuplicate(ImplementedFunction left, ImplementedFunction right)
 => left.Signature.Equals(right.Signature);
예제 #4
0
 public bool TryCreateOverload(Function function, out ImplementedFunction overload, Project core)
 {
     overload = null;
     return(false);
 }
        /// <inheritdoc/>
        public bool TryGetFunctionVariant(Function function, out ImplementedFunction overload, Project core)
        {
            if (!IsApplicable(function))
            {
                overload = null;
                return(false);
            }

            var lastParameterType = function.Parameters.Last().Type;
            var newReturnType     = new TypeSignatureBuilder(lastParameterType)
                                    .WithIndirectionLevel(lastParameterType.IndirectionLevels - 1)
                                    .WithArrayDimensions(0)
                                    .Build();

            var newParameters = SkipLastExtension.SkipLast(function.Parameters, 1).ToList();
            var newName       = function.Name.Singularize(false);

            var functionBuilder = new FunctionSignatureBuilder(function)
                                  .WithName(newName)
                                  .WithReturnType(newReturnType);

            var sb        = new StringBuilder();
            var strParams = newParameters.Select(Convert).Concat(new[] { "&ret" });

            sb.AppendLine("// ReturnTypeOverloader");
            sb.AppendLine($"{newReturnType} ret = default;");
            sb.Append($"{function.Name}(");
            sb.Append(string.Join(", ", strParams));
            sb.AppendLine(");");
            sb.AppendLine("return ret;");

            if (!newParameters.Any())
            {
                overload = new ImplementedFunction
                           (
                    functionBuilder
                    .WithParameters(newParameters)
                    .Build(), sb, function, true
                           );

                return(true);
            }

            var sizeParameterType = newParameters.Last().Type;

            if ((sizeParameterType.Name != "int" && sizeParameterType.Name != "uint") || sizeParameterType.IsPointer)
            {
                overload = new ImplementedFunction
                           (
                    functionBuilder
                    .WithParameters(newParameters)
                    .Build(), sb, function, true
                           );

                return(true);
            }

            var n = newParameters.Last().Name;

            sb.Insert
            (
                0,
                $"const {(sizeParameterType.Name == "uint" ? "uint " : "int ")}{(Utilities.CSharpKeywords.Contains(n) ? "@" : "")}{n} = 1;\n"
            );
            newParameters = SkipLastExtension.SkipLast(newParameters, 1).ToList();
            overload      = new ImplementedFunction
                            (
                functionBuilder
                .WithParameters(newParameters)
                .Build(), sb, function, true
                            );
            return(true);

            string Convert(Parameter x)
            {
                var pre = x.Type.IsOut ? "out " : string.Empty;

                return(pre + (Utilities.CSharpKeywords.Contains(x.Name) ? $"@{x.Name}" : x.Name));
            }
        }
예제 #6
0
        public bool TryGetFunctionVariant(Function function, out ImplementedFunction overload, Project core)
        {
            // SilkTouch currently can't properly marshal string spans, so we need to help out.
            var sb     = new StringBuilder();
            var pl     = new List <Parameter>();
            var ep     = new List <string>();
            var varied = false;

            sb.AppendLine("// StringArrayOverloader");
            pl.AddRange(function.Parameters);
            for (var i = 0; i < pl.Count; i++)
            {
                var parameter = pl[i];
                if (parameter.Type.ToString() == "char**" || parameter.Type.ToString() == "byte**")
                {
                    pl[i] = new ParameterSignatureBuilder(parameter).WithType
                            (
                        new Type
                    {
                        Name = "string", ArrayDimensions = 1, OriginalName = parameter.Type.OriginalName
                    }
                            )
                            .WithName(parameter.Name + "Sa")
                            .Build();
                    varied = true;
                    sb.AppendLine
                    (
                        $"var {parameter.Name} = ({parameter.Type}) SilkMarshal.StringArrayToPtr({parameter.Name}Sa);"
                    );
                    ep.Add($"SilkMarshal.CopyPtrToStringArray((nint) {parameter.Name}, {parameter.Name}Sa);");
                    ep.Add($"SilkMarshal.Free((nint) {parameter.Name});");
                }
            }

            if (function.ReturnType.ToString() != "void")
            {
                sb.Append("var ret = ");
            }

            sb.AppendLine
            (
                $"{function.Name}" +
                "(" + string.Join
                (
                    ", ",
                    function.Parameters.Select
                    (
                        x => (x.Type.IsIn ? "in " : string.Empty) + (x.Type.IsOut ? "out " : string.Empty) +
                        (x.Type.IsByRef ? "ref " : string.Empty) + (Utilities.CSharpKeywords.Contains
                                                                        (x.Name)
                                 ? "@"
                                 : string.Empty) + x.Name
                    )
                ) + ");"
            );

            foreach (var epilogueLine in ep)
            {
                sb.AppendLine(epilogueLine);
            }

            if (function.ReturnType.ToString() != "void")
            {
                sb.AppendLine("return ret;");
            }

            if (varied)
            {
                overload = new ImplementedFunction
                               (new FunctionSignatureBuilder(function).WithParameters(pl).Build(), sb, function);
                return(true);
            }

            overload = null;
            return(false);
        }
예제 #7
0
        public bool TryCreateOverload(Function function, out ImplementedFunction overload, Project core)
        {
            if (function.NativeName == "clEnqueueSVMMigrateMem" || function.NativeName == "clEnqueueNativeKernel")
            {
                // BUG these functions think a span variant exists where one doesnt, was unable to filter out.
                overload = null;
                return(false);
            }

            var @params = new List <Parameter>(function.Parameters);
            var sb      = new StringBuilder();

            sb.AppendLine("// IntPtrOverloader");
            if (function.ReturnType.ToString() != "void")
            {
                sb.Append("return ");
            }

            sb.Append($"{function.Name}(");
            var ret = false;

            for (var i = 0; i < function.Parameters.Count; i++)
            {
                var parameter     = function.Parameters[i];
                var parameterName = Utilities.CSharpKeywords.Contains(parameter.Name)
                    ? $"@{parameter.Name}"
                    : parameter.Name;
                if (parameter.Type.IsIntPtr() && !(parameter.Type.IsOut))
                {
                    @params[i] = new ParameterSignatureBuilder(parameter)
                                 .WithType(new TypeSignatureBuilder(parameter.Type).WithName("int").Build())
                                 .Build();
                    sb.Append($"new IntPtr({parameterName})");
                    ret = true;
                }
                else if (parameter.Type.IsUIntPtr() && !(parameter.Type.IsOut))
                {
                    @params[i] = new ParameterSignatureBuilder(parameter)
                                 .WithType(new TypeSignatureBuilder(parameter.Type).WithName("uint").Build())
                                 .Build();
                    sb.Append($"new UIntPtr({parameterName})");
                    ret = true;
                }
                else
                {
                    var prefix = parameter.Type.IsOut ? "out " : parameter.Type.IsByRef ? "ref " : string.Empty;
                    sb.Append($"{prefix}{parameterName}");
                }

                if (i != function.Parameters.Count - 1)
                {
                    sb.Append(", ");
                }
            }

            sb.AppendLine(");");

            if (ret)
            {
                overload = new ImplementedFunction(new FunctionSignatureBuilder(function).WithParameters(@params).Build(), sb, function);
                return(true);
            }

            overload = null;
            return(false);
        }
예제 #8
0
        public bool TryCreateOverload(Function function, out ImplementedFunction overload, Project core)
        {
            // SuperInvoke currently can't properly marshal string spans, so we need to help out.
            var sb     = new StringBuilder();
            var pl     = new List <Parameter>();
            var ep     = new List <string>();
            var varied = false;

            sb.AppendLine("// StringArrayOverloader");
            pl.AddRange(function.Parameters);
            for (var i = 0; i < pl.Count; i++)
            {
                var parameter = pl[i];
                if (parameter.Type.ToString() == "char**" || parameter.Type.ToString() == "byte**")
                {
                    pl[i] = new ParameterSignatureBuilder(parameter).WithType
                            (
                        new Type
                    {
                        Name = "string", ArrayDimensions = 1
                    }
                            )
                            .WithName(parameter.Name + "Sa")
                            .Build();
                    varied = true;
                    sb.AppendLine
                    (
                        $"var {parameter.Name} = ({parameter.Type}) SilkMarshal.MarshalStringArrayToPtr({parameter.Name}Sa);"
                    );
                    ep.Add($"SilkMarshal.CopyPtrToStringArray((IntPtr) {parameter.Name}, {parameter.Name}Sa);");
                }
            }

            if (function.ReturnType.ToString() != "void")
            {
                sb.Append("var ret = ");
            }

            sb.AppendLine
            (
                $"{function.Name}" +
                $"({string.Join(", ", function.Parameters.Select(x => (x.Type.IsByRef ? "ref " : string.Empty) + x.Name))});"
            );

            foreach (var epilogueLine in ep)
            {
                sb.AppendLine(epilogueLine);
            }

            if (function.ReturnType.ToString() != "void")
            {
                sb.AppendLine("return ret;");
            }

            if (varied)
            {
                overload = new ImplementedFunction
                               (new FunctionSignatureBuilder(function).WithParameters(pl).Build(), sb, function);
                return(true);
            }

            overload = null;
            return(false);
        }