Bug 17558 - Bug in AOT
Summary: Bug in AOT
Status: VERIFIED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: 7.0.6.x
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: 7.2.1
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-02-03 06:03 UTC by Grigory (Playtika)
Modified: 2014-03-20 09:06 UTC (History)
6 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Full repro project (12.62 KB, application/octet-stream)
2014-02-04 03:19 UTC, Grigory (Playtika)
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FIXED

Description Grigory (Playtika) 2014-02-03 06:03:02 UTC
I use AggressiveInlining on many small methods.
It is 7.0.4 compiled code successfully, 7.0.6 Fails.
Both LLVM and usual compiler fail.

Code:
using System;
using System.Runtime.CompilerServices;

namespace Monosyne
{
    public struct Color: IEquatable<Color>
    {
        public UInt32 ARGB;

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public Color(UInt32 value)
        {
            ARGB = value;
        }

        #region IEquatable implementation

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public bool Equals(Color other)
        {
            return ARGB == other.ARGB;
        }

        #endregion

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        static public Color LinearInterpolation(Color color1, Color color2, float amount)
        {
            return new Color((byte)MathHelper.LinearInterpolation(color1.R, color2.R, amount),
                             (byte)MathHelper.LinearInterpolation(color1.G, color2.G, amount),
                             (byte)MathHelper.LinearInterpolation(color1.B, color2.B, amount),
                             (byte)MathHelper.LinearInterpolation(color1.A, color2.A, amount));
        }

        static public readonly Color Transparent = new Color(0, 0, 0, 0);

        static public readonly Color Black = new Color(0, 0, 0);

        static public readonly Color Red = new Color(255, 0, 0);

        static public readonly Color Green = new Color(0, 255, 0);

        static public readonly Color Blue = new Color(0, 0, 255);

        static public readonly Color Yellow = new Color(255, 255, 0);

        static public readonly Color Aqua = new Color(0, 255, 255);

        static public readonly Color White = new Color(255, 255, 255);

        static public readonly Color Fuchsia = new Color(255, 0, 255);

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public Color(ColorF color)
        {
            ARGB = PackColor((byte)MathHelper.Clamp(color.R * 255, 0, 255),
                             (byte)MathHelper.Clamp(color.G * 255, 0, 255),
                             (byte)MathHelper.Clamp(color.B * 255, 0, 255),
                             (byte)MathHelper.Clamp(color.A * 255, 0, 255));
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public Color(byte r, byte g, byte b, byte a)
        {
            ARGB = PackColor(r, g, b, a);
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public Color(byte r, byte g, byte b)
        {
            ARGB = PackColor(r, g, b, 255);
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static UInt32 PackColor(byte R, byte G, byte B, byte A)
        {
            UInt32 color = R;
            color |= (uint)G << 8;
            color |= (uint)B << 16;
            color |= (uint)A << 24;
            return color;
        }

        public byte R
        {
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            get{ return (byte)(ARGB & 0xff);}
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            set
            {
                ARGB &= 0xffffff00;
                ARGB |= value;
            }
        }

        public byte G
        {
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            get{ return (byte)((ARGB >> 8) & 0xff);}
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            set
            {
                ARGB &= 0xffff00ff;
                ARGB |= ((UInt32)value) << 8;
            }
        }

        public byte B
        {
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            get{ return (byte)((ARGB >> 16) & 0xff);}
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            set
            {
                ARGB &= 0xff00ffff;
                ARGB |= ((UInt32)value) << 16;
            }
        }

        public byte A
        {
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            get{ return (byte)((ARGB >> 24) & 0xff);}
            [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
            set
            {
                ARGB &= 0x00ffffff;
                ARGB |= ((UInt32)value) << 24;
            }
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static void Multiply(ref Color value1, ref Color value2, out Color result)
        {
            result.ARGB = PackColor((byte)((value1.R * value2.R * 258) >> 16),
                                    (byte)((value1.G * value2.G * 258) >> 16),
                                    (byte)((value1.B * value2.B * 258) >> 16),
                                    (byte)((value1.A * value2.A * 258) >> 16));
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static Color Multiply(Color value1, Color value2)
        {
            value1.ARGB = PackColor((byte)((value1.R * value2.R * 258) >> 16),
                                    (byte)((value1.G * value2.G * 258) >> 16),
                                    (byte)((value1.B * value2.B * 258) >> 16),
                                    (byte)((value1.A * value2.A * 258) >> 16));
            return value1;
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static Color Multiply(Color value1, float factor)
        {
            value1.ARGB = PackColor((byte)Math.Min(value1.R * factor, 255),
                                    (byte)Math.Min(value1.G * factor, 255),
                                    (byte)Math.Min(value1.B * factor, 255),
                                    (byte)Math.Min(value1.A * factor, 255));
            return value1;
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static void Multiply(ref Color value1, float factor, out Color res)
        {
            res.ARGB = PackColor((byte)Math.Min(value1.R * factor, 255),
                                 (byte)Math.Min(value1.G * factor, 255),
                                 (byte)Math.Min(value1.B * factor, 255),
                                 (byte)Math.Min(value1.A * factor, 255));
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static Color Divide(Color value1, float factor)
        {
            value1.ARGB = PackColor((byte)(value1.R / factor),
                                    (byte)(value1.G / factor),
                                    (byte)(value1.B / factor),
                                    (byte)(value1.A / factor));
            return value1;
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static void Divide(ref Color value1, float factor, out Color res)
        {
            res.ARGB = PackColor((byte)(value1.R / factor),
                                 (byte)(value1.G / factor),
                                 (byte)(value1.B / factor),
                                 (byte)(value1.A / factor));
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static Color Add(Color value1, Color value2)
        {
            value1.ARGB = PackColor((byte)Math.Min(value1.R + value2.R, 255),
                                    (byte)Math.Min(value1.G + value2.G, 255),
                                    (byte)Math.Min(value1.B + value2.B, 255),
                                    (byte)Math.Min(value1.A + value2.A, 255));
            return value1;
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static void Add(ref Color value1, ref Color value2, out Color res)
        {
            res.ARGB = PackColor((byte)Math.Min(value1.R + value2.R, 255),
                                 (byte)Math.Min(value1.G + value2.G, 255),
                                 (byte)Math.Min(value1.B + value2.B, 255),
                                 (byte)Math.Min(value1.A + value2.A, 255));
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static Color Sub(Color value1, Color value2)
        {
            value1.ARGB = PackColor((byte)Math.Max(value1.R - value2.R, 0),
                                    (byte)Math.Max(value1.G - value2.G, 0),
                                    (byte)Math.Max(value1.B - value2.B, 0),
                                    (byte)Math.Max(value1.A - value2.A, 0));
            return value1;
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static void Sub(ref Color value1, ref Color value2, out Color res)
        {
            res.ARGB = PackColor((byte)Math.Max(value1.R - value2.R, 0),
                                 (byte)Math.Max(value1.G - value2.G, 0),
                                 (byte)Math.Max(value1.B - value2.B, 0),
                                 (byte)Math.Max(value1.A - value2.A, 0));
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static Color operator * (Color value1, Color value2)
        {
            value1.ARGB = PackColor((byte)((value1.R * value2.R * 258) >> 16),
                                    (byte)((value1.G * value2.G * 258) >> 16),
                                    (byte)((value1.B * value2.B * 258) >> 16),
                                    (byte)((value1.A * value2.A * 258) >> 16));
            return value1;
        }

        [MethodImplAttribute(MethodImplSettings.AggressiveInlining)]
        public static Color operator + (Color value1, Color value2)
        {
            value1.ARGB = PackColor((byte)Math.Min(value1.R + value2.R, 255),
                                    (byte)Math.Min(value1.G + value2.G, 255),
                                    (byte)Math.Min(value1.B + value2.B, 255),
                                    (byte)Math.Min(value1.A + value2.A, 255));
            return value1;
        }
    }
}
Comment 1 Grigory (Playtika) 2014-02-03 06:05:42 UTC
[13:37:20][Step 4/4]          AOT Compilation exited with code 138, command:
[13:37:20][Step 4/4]          MONO_PATH=/Users/sergey.greshnov/Desktop/buildAgent/work/IOS.NG/Build/_tmp/iPhone/Release/CaesarsSlots.IOS/mtouch-cache/Build /Developer/MonoTouch/usr/bin/arm-darwin-mono-boehm --debug -O=gsharedvt  --aot=mtriple=armv7-ios,nimt-trampolines=512,full,static,asmonly,direct-icalls,nodebug,dwarfdebug,outfile=/Users/sergey.greshnov/Desktop/buildAgent/work/IOS.NG/Build/_tmp/iPhone/Release/CaesarsSlots.IOS/mtouch-cache/MonosyneIOS.dll.armv7.s "/Users/sergey.greshnov/Desktop/buildAgent/work/IOS.NG/Build/_tmp/iPhone/Release/CaesarsSlots.IOS/mtouch-cache/Build/MonosyneIOS.dll"
[13:37:20][Step 4/4]          Invoking method 'Monosyne.Color:.cctor ()' when running in no-exec mode.
Comment 2 Grigory (Playtika) 2014-02-03 07:52:06 UTC
MethodImplSettings == MethodImplOptions
Comment 3 Zoltan Varga 2014-02-03 08:51:20 UTC
Please add a complete testcase.
Comment 4 Grigory (Playtika) 2014-02-03 09:09:37 UTC
1. Create sample IPhone project.
2. Add the following code to ColorF.cs:

using System;
using System.Runtime.CompilerServices;

namespace simpleIOS
{
    public struct ColorF
    {
        public static readonly ColorF Transparent = new ColorF();

		[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
		public static void Add()
		{
		}

        public static ColorF operator + (ColorF value1, ColorF value2)
        {
			ColorF.Add();
			return new ColorF();
        }
    }
}


This doesn't even compile.
Comment 5 Zoltan Varga 2014-02-03 09:37:02 UTC
Can't reproduce this.
Comment 6 Grigory (Playtika) 2014-02-04 03:19:00 UTC
Created attachment 5968 [details]
Full repro project

Attached repro project. 
It fails to compile on 3 our dev machines with 

Xamarin.iOS
Version: 7.0.6.168 (Enterprise Edition)
Comment 7 Zoltan Varga 2014-02-04 03:55:33 UTC
Fixed in mono 7604aae1b1b11ba78da29d83fe255d2f8e773226/mt c7e5526e05c7f34a6e7f5674df2082b57ce34321.

A workaround is to avoid the use of AggressiveInlining attribute on methods in classes which have a static constructor, i.e. ColorF in this case.
Comment 8 Miguel de Icaza [MSFT] 2014-02-06 09:48:24 UTC
Zoltan, 

With the fix, does this mean that having a static constructor in a class will disable AggressiveInlining when doing AOT?
Comment 9 Zoltan Varga 2014-02-06 13:59:01 UTC
Inlining was already disabled in those cases because the inlined code would have to invoke the static cctor of the type, so there would be a call in the code anyway.
Comment 10 Icer addis 2014-02-27 17:00:57 UTC
I ran into this issue today as well. It would be very useful if you could apply an attribute to a class that would prevent a static cctor from being generated (the compiler would generate an error if one was created). That way we would have confidence that our inlining is being performed when we expect it to be and we would keep ourselves from hindering it.
Comment 11 Zoltan Varga 2014-02-28 20:08:45 UTC
This has been fixed so methods with the AggressiveInlining attribute will be inlined even if they have a static cctor.
Comment 12 Zoltan Varga 2014-02-28 20:11:02 UTC
The last issue is fixed in mono eef1f283a69c9f6eea6fdb66812b4db46842940a/mt cd4a7a810019421bb470d2562da190662443ba19.
Comment 13 Zoltan Varga 2014-03-12 18:02:22 UTC
-> FIXED.
Comment 14 Shruti 2014-03-20 07:45:32 UTC
I have launched the attached project 'Full Repro Project'. It has been build and deployed successfully  on simulator.

Build Successful Log : 
https://gist.github.com/Sadik1/d58e095b62c9e6875a1f

Screen Cast Info :
http://screencast.com/t/arS0b79LFAe

Environment Info:
XS 4.2.4 (build 32) 
X.iOS 7.2.1.20

Hence closing this issue......Please let me know If anything additional revert to check.