Example #1
0
        private static Func <IExtractContext, string[]> Apply(
            ILocalVariableInformation target,
            ITypeInformation targetType,
            DecodeContext decodeContext)
        {
            var si = decodeContext.PopStack();

            var codeInformation = decodeContext.CurrentCode;

            return(extractContext =>
            {
                var rightExpression = extractContext.GetRightExpression(targetType, si);
                if (rightExpression == null)
                {
                    throw new InvalidProgramSequenceException(
                        "Invalid store operation: Location={0}, StackType={1}, LocalType={2}, SymbolName={3}",
                        codeInformation.RawLocation,
                        si.TargetType.FriendlyName,
                        targetType.FriendlyName,
                        target);
                }

                return new[] { string.Format(
                                   "{0} = {1}",
                                   extractContext.GetSymbolName(target),
                                   rightExpression) };
            });
        }
Example #2
0
        private static ExpressionEmitter Prepare(
            ILocalVariableInformation target, ITypeInformation targetType, DecodeContext decodeContext, bool isReference)
        {
            targetType = isReference ? targetType.MakeByReference() : targetType;

            var symbol = decodeContext.PushStack(targetType);

            return((extractContext, _) => new[] { string.Format(
                                                      "{0} = {1}{2}",
                                                      extractContext.GetSymbolName(symbol),
                                                      // NOTE: Don't check "targetType.IsByReference" instead "isReference."
                                                      //   Because it's maybe double encoded byref type.
                                                      isReference ? "&" : string.Empty,
                                                      extractContext.GetSymbolName(target)) });
        }
Example #3
0
        private static (ITypeInformation type, ILocalVariableInformation variable, string format) GetArg0ParameterInformation(
            DecodeContext decodeContext,
            ref IMethodInformation method,
            IParameterInformation parameter0,
            ILocalVariableInformation arg0,
            ref ITypeInformation arg0ValueType,
            ref ILocalVariableInformation requiredBoxingAtArg0PointerVariable,
            ref ILocalVariableInformation requiredCastingAtArg0PointerVariable,
            ref bool isVirtualCall)
        {
            Debug.Assert(method.IsStatic ||
                         parameter0.TargetType.Equals(method.DeclaringType) ||
                         (parameter0.TargetType.IsByReference && parameter0.TargetType.ElementType.Equals(method.DeclaringType)));

            // Required boxing at the arg0
            if (arg0ValueType != null)
            {
                if (!arg0.TargetType.IsByReference)
                {
                    throw new InvalidProgramSequenceException(
                              "Cannot apply constrained prefix, arg0 isn't byref: Location={0}, Arg0Type={1}",
                              decodeContext.CurrentCode.RawLocation,
                              arg0.TargetType.FriendlyName);
                }

                // VERY DIRTY: The arg0 (managed pointer) uses below.
                requiredBoxingAtArg0PointerVariable = arg0;

                // VERY DIRTY: Make the boxing expression below,
                //   it's reserving for the boxed value symbol at the evaluation stack.
                var arg0BoxedSymbol = decodeContext.PushStack(
                    new BoxedValueTypeInformation(arg0ValueType));
                decodeContext.PopStack();

                return(parameter0.TargetType, arg0BoxedSymbol, "{0}");
            }
            // If it's virtual method
            else if (isVirtualCall)
            {
                // Invoke interface method with the inline boxed-type instance.
                //   ex: ((IFoo)foo).Bar(...)
                //   If not inlined (ex: bound to local variable), arg0 doesn't box type. Next to the else block.
                if (method.DeclaringType.IsInterface && arg0.TargetType.IsBoxedType)
                {
                    // VERY DIRTY: The arg0 (boxed value) uses below.
                    requiredCastingAtArg0PointerVariable = arg0;
                    arg0ValueType = arg0.TargetType;

                    // VERY DIRTY: Make the implicitly cast expression below,
                    //   it's reserving for the casted value symbol at the evaluation stack.
                    var arg0CastedSymbol = decodeContext.PushStack(method.DeclaringType);
                    decodeContext.PopStack();

                    return(parameter0.TargetType, arg0CastedSymbol, "il2c_adjusted_reference({0})");
                }
                // Invoke interface method with the class-type instance and
                // IL2C detected here for can cast statically.
                else if (method.DeclaringType.IsInterface &&
                         arg0.TargetType.IsClass &&
                         method.DeclaringType.IsAssignableFrom(arg0.TargetType))
                {
                    // All declared methods from derived to base types.
                    var allDeclaredMethods = arg0.TargetType.AllInheritedDeclaredMethods;

                    var m = method;
                    var implementationMethod = allDeclaredMethods.First(
                        dm => MetadataUtilities.VirtualMethodSignatureComparer.Equals(dm, m));

                    Debug.Assert(implementationMethod.DeclaringType.IsAssignableFrom(arg0.TargetType));

                    // Drop virtual call and turn to the direct call (devirtualize)
                    isVirtualCall = false;
                    method        = implementationMethod;
                    return(arg0.TargetType, arg0, "il2c_adjusted_reference({0})");
                }
                else if (!(parameter0.TargetType.IsClass && arg0.TargetType.IsClass &&
                           parameter0.TargetType.IsAssignableFrom(arg0.TargetType)))
                {
                    // Include adjust offset expression
                    return(parameter0.TargetType, arg0, "il2c_adjusted_reference({0})");
                }
            }

            return(parameter0.TargetType, arg0, "{0}");
        }
Example #4
0
        public static Func <IExtractContext, string[]> Apply(
            IMethodInformation method,
            DecodeContext decodeContext,
            bool isVirtualCall)
        {
            // ECMA-335 I.12.4.1.4: Virtual calling convention

            // This method is too complex because it will try devirtualizing.

            //////////////////////////////////////////////////////////
            // Step 1:

            // Constrained prefix applied, drop virtual call and hack the boxing for arg0 if required.
            //   (See ConstrainedConverter.)
            ITypeInformation arg0ValueType = null;
            var prefixCode = decodeContext.PrefixCode;

            if (prefixCode?.OpCode == OpCodes.Constrained)
            {
                // 'The constrained. prefix is permitted only on a callvirt instruction.'
                if (!isVirtualCall)
                {
                    throw new InvalidProgramSequenceException(
                              "Cannot apply constrained prefix: Location={0}",
                              decodeContext.CurrentCode.RawLocation);
                }

                // ECMA-335 III.2.1 constrained. - (prefix) invoke a member on a value of a variable type
                var constrainedType = (ITypeInformation)(prefixCode.Operand);

                // 'If thisType is a value type...'
                if (constrainedType.IsValueType)
                {
                    // All declared methods from derived to base types.
                    var allDeclaredMethods = constrainedType.AllInheritedDeclaredMethods;

                    // '...and thisType implements method then'
                    var implementationMethod = allDeclaredMethods.First(
                        dm => MetadataUtilities.VirtualMethodSignatureComparer.Equals(dm, method));

                    // Drop virtual call and turn to the direct call (devirtualize)
                    isVirtualCall = false;
                    method        = implementationMethod;

                    // '...and thisType does not implement method then'
                    if (!implementationMethod.DeclaringType.Equals(constrainedType))
                    {
                        // 'ptr is dereferenced, boxed, and passed as the ‘this’ pointer to the callvirt of method'

                        // VERY DIRTY: The constrained type uses below.
                        arg0ValueType = constrainedType;
                    }
                }
            }

            //////////////////////////////////////////////////////////
            // Step 2:

            ILocalVariableInformation requiredBoxingAtArg0PointerVariable  = null;
            ILocalVariableInformation requiredCastingAtArg0PointerVariable = null;

            // Construct parameters with expressions.
            var pairParameters = method.Parameters.
                                 Reverse(). // arg(n - 1) ... arg0
                                 Select(parameter =>
            {
                var arg = decodeContext.PopStack();
                return((parameter.Index == 0) ?
                       GetArg0ParameterInformation(
                           decodeContext, ref method, parameter, arg,
                           ref arg0ValueType,
                           ref requiredBoxingAtArg0PointerVariable,
                           ref requiredCastingAtArg0PointerVariable,
                           ref isVirtualCall) :
                       (type: parameter.TargetType, variable: arg, format: "{0}"));
            }).
                                 Reverse().
                                 ToArray();

            //////////////////////////////////////////////////////////
            // Step 3: Fixing special cases

            var codeInformation = decodeContext.CurrentCode;
            ILocalVariableInformation result;

            // TODO: HACK: IL2C can't handle the generic types/methods in this version.
            //   Roslyn will generate implementation for the event member with using for
            //   "System.Threading.Interlocked.CompareExchange<T>(...)" method.
            //   It's special resolver for event member.
            if ((method.UniqueName == "T System.Threading.Interlocked::CompareExchange(T&,T,T)") &&
                pairParameters[1].variable.TargetType.IsReferenceType)
            {
                result = decodeContext.PushStack(pairParameters[1].variable.TargetType);

                return(extractContext =>
                {
                    var parameters = pairParameters.Select(parameter =>
                                                           new Utilities.RightExpressionGivenParameter(
                                                               parameter.variable.TargetType,
                                                               parameter.variable,
                                                               string.Format(parameter.format, extractContext.GetSymbolName(parameter.variable)))).
                                     ToArray();

                    var parameterString = Utilities.GetGivenParameterDeclaration(
                        parameters,
                        extractContext,
                        codeInformation);

                    return new[]
                    {
                        string.Format(
                            "{0} = ({1})System_Threading_Interlocked_CompareExchange_6({2})",
                            extractContext.GetSymbolName(result),
                            pairParameters[1].variable.TargetType.CLanguageTypeName,
                            parameterString)
                    };
                });
            }

            if (method.ReturnType.IsVoidType)
            {
                // HACK: If we will call the RuntimeHelpers.InitializeArray, we can memoize array type hint.
                //   (See LdtokenConverter.)
                if (method.FriendlyName.StartsWith(
                        "System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray"))
                {
                    Debug.Assert(pairParameters.Length == 2);
                    Debug.Assert(pairParameters[1].variable.HintInformation is string);

                    decodeContext.PrepareContext.RegisterDeclaredValuesHintType(
                        (string)pairParameters[1].variable.HintInformation,
                        pairParameters[0].variable.TargetType);
                }

                result = null;
            }
            else
            {
                result = decodeContext.PushStack(method.ReturnType);
            }

            // Register callee method declaring type (at the file scope).
            decodeContext.PrepareContext.RegisterType(method.DeclaringType, decodeContext.Method);

            return(extractContext =>
            {
                var receiveResultExpression = (result != null) ?
                                              string.Format("{0} = ", extractContext.GetSymbolName(result)) :
                                              string.Empty;

                var parameters = pairParameters.Select(parameter =>
                                                       new Utilities.RightExpressionGivenParameter(
                                                           parameter.type,
                                                           parameter.variable,
                                                           string.Format(parameter.format, extractContext.GetSymbolName(parameter.variable)))).
                                 ToArray();

                var parameterString = Utilities.GetGivenParameterDeclaration(
                    parameters,
                    extractContext,
                    codeInformation);

                // Construct call expression between virtual and non-virtual.
                string callExpression;
                if (isVirtualCall && method.IsVirtual && !method.IsSealed)
                {
                    var overloadIndex = method.DeclaringType.CalculatedVirtualMethods.
                                        First(entry => entry.method.Equals(method)).
                                        overloadIndex;

                    callExpression = string.Format(
                        "{0}{1}->vptr0__->{2}({3})",
                        receiveResultExpression,
                        extractContext.GetSymbolName(pairParameters[0].variable),
                        method.GetCLanguageDeclarationName(overloadIndex),
                        parameterString);
                }
                else
                {
                    callExpression = string.Format(
                        "{0}{1}({2})",
                        receiveResultExpression,
                        method.CLanguageFunctionName,
                        parameterString);
                }

                // If requires boxing expression
                if (requiredBoxingAtArg0PointerVariable != null)
                {
                    Debug.Assert(arg0ValueType != null);

                    // Emit call expression with boxing expression.
                    return new[] {
                        string.Format(
                            "{0} = il2c_box({1}, {2})",
                            extractContext.GetSymbolName(pairParameters[0].variable),
                            extractContext.GetSymbolName(requiredBoxingAtArg0PointerVariable),
                            arg0ValueType.MangledUniqueName),
                        callExpression
                    };
                }
                // If requires casting expression
                else if (requiredCastingAtArg0PointerVariable != null)
                {
                    // Emit call expression with casting expression.
                    return new[] {
                        string.Format(
                            "{0} = il2c_cast_from_boxed_to_interface({1}, {2}, {3}, {4})",
                            extractContext.GetSymbolName(pairParameters[0].variable),
                            method.DeclaringType.MangledUniqueName,
                            arg0ValueType.ElementType.CLanguageStaticSizeOfExpression,
                            arg0ValueType.CalculateInterfaceIndex(method.DeclaringType),
                            extractContext.GetSymbolName(requiredCastingAtArg0PointerVariable)),
                        callExpression
                    };
                }
                else
                {
                    // Emit only call expression
                    return new[] { callExpression };
                }
            });
        }
Example #5
0
        private static (ITypeInformation type, ILocalVariableInformation variable, string format) GetArg0ParameterInformation(
            DecodeContext decodeContext,
            ref IMethodInformation method,
            IParameterInformation parameter0,
            ILocalVariableInformation arg0,
            ref ITypeInformation arg0ValueType,
            ref ILocalVariableInformation requiredBoxingAtArg0PointerVariable,
            ref ILocalVariableInformation requiredCastingAtArg0PointerVariable,
            ref bool isVirtualCall)
        {
            // Required boxing at the arg0
            if (arg0ValueType != null)
            {
                if (!arg0.TargetType.IsByReference)
                {
                    throw new InvalidProgramSequenceException(
                              "Cannot apply constrained prefix, arg0 isn't byref: Location={0}, Arg0Type={1}",
                              decodeContext.CurrentCode.RawLocation,
                              arg0.TargetType.FriendlyName);
                }

                // VERY DIRTY: The arg0 (managed pointer) uses below.
                requiredBoxingAtArg0PointerVariable = arg0;

                // VERY DIRTY: Make the boxing expression below,
                //   it's reserving for the boxed value symbol at the evaluation stack.
                var arg0BoxedSymbol = decodeContext.PushStack(
                    new BoxedValueTypeInformation(arg0ValueType));
                decodeContext.PopStack();

                return(parameter0.TargetType, arg0BoxedSymbol, "{0}");
            }
            // If it's virtual method
            else if (isVirtualCall)
            {
                // Invoke interface method with the inline boxed-type instance.
                //   ex: ((IFoo)foo).Bar(...)
                //   If not inlined (ex: bound to local variable), arg0 doesn't box type. Next to the else block.
                if (method.DeclaringType.IsInterface && arg0.TargetType.IsBoxedType)
                {
                    // VERY DIRTY: The arg0 (boxed value) uses below.
                    requiredCastingAtArg0PointerVariable = arg0;
                    arg0ValueType = arg0.TargetType;

                    // VERY DIRTY: Make the implicitly cast expression below,
                    //   it's reserving for the casted value symbol at the evaluation stack.
                    var arg0CastedSymbol = decodeContext.PushStack(method.DeclaringType);
                    decodeContext.PopStack();

                    return(parameter0.TargetType, arg0CastedSymbol, "il2c_adjusted_reference({0})");
                }
                else
                {
                    // Include adjust offset expression
                    return(parameter0.TargetType, arg0, "il2c_adjusted_reference({0})");
                }
            }
            else
            {
                return(parameter0.TargetType, arg0, "{0}");
            }
        }
Example #6
0
        public override Func <IExtractContext, string[]> Apply(
            IMethodInformation ctor, DecodeContext decodeContext)
        {
            if (!ctor.IsConstructor)
            {
                throw new InvalidProgramSequenceException(
                          "Invalid new object constructor: Location={0}, Method={1}",
                          decodeContext.CurrentCode.RawLocation,
                          ctor.FriendlyName);
            }

            // Generate the constructor's argument expressions.
            var type = ctor.DeclaringType;
            ILocalVariableInformation thisSymbol = null;

            var pairParameters = new LinkedList <Utilities.RightExpressionGivenParameter>();

            foreach (var parameter in ctor.Parameters.Reverse())
            {
                // Except this parameter
                if (pairParameters.Count < (ctor.Parameters.Length) - 1)
                {
                    pairParameters.AddFirst(new Utilities.RightExpressionGivenParameter(
                                                parameter.TargetType,
                                                decodeContext.PopStack()));
                }
                // "this" parameter
                else
                {
                    Debug.Assert(thisSymbol == null);

                    // Instance from get_uninitialized_object
                    thisSymbol = decodeContext.PushStack(type, ctor);

                    pairParameters.AddFirst(new Utilities.RightExpressionGivenParameter(
                                                type,
                                                thisSymbol));
                }
            }

            Debug.Assert(thisSymbol != null);

            var codeInformation = decodeContext.CurrentCode;

            // Specialized the delegate type:
            //   We can use for instantiate the delegate instance with "il2c_new_delegate()."
            if (type.IsDelegate)
            {
                if (type.IsAbstract || type.IsDelegateType || type.IsMulticastDelegateType)
                {
                    throw new InvalidProgramSequenceException(
                              "Invalid delegate type: Location={0}, Method={1}",
                              codeInformation.RawLocation,
                              type.FriendlyName);
                }

                if (!(ctor.Parameters.Length == 2) &&
                    (ctor.Parameters[0].TargetType.IsObjectType) &&
                    (ctor.Parameters[0].TargetType.IsIntPtrType))
                {
                    throw new InvalidProgramSequenceException(
                              "Invalid delegate constructor: Location={0}, Method={1}",
                              codeInformation.RawLocation,
                              ctor.FriendlyName);
                }

                return(extractContext =>
                {
                    var parameterString = Utilities.GetGivenParameterDeclaration(
                        pairParameters.Skip(1).ToArray(), extractContext, codeInformation);

                    return new[]
                    {
                        string.Format(
                            "{0} = il2c_new_delegate({1}, {2})",
                            extractContext.GetSymbolName(thisSymbol),
                            type.MangledName,
                            parameterString)
                    };
                });
            }

            var overloadIndex = ctor.OverloadIndex;

            return(extractContext =>
            {
                var parameterString = Utilities.GetGivenParameterDeclaration(
                    pairParameters.ToArray(), extractContext, codeInformation);

                // newobj opcode can handle value type with parameter applied constructor.
                if (type.IsValueType)
                {
                    // If constructor's arguments greater than or equal 2 (this and others)
                    if (pairParameters.Count >= 2)
                    {
                        var typeName = type.CLanguageTypeName;
                        return new[] {
                            string.Format(
                                "memset(&{0}, 0x00, {1})",
                                extractContext.GetSymbolName(thisSymbol),
                                type.CLanguageStaticSizeOfExpression),
                            (overloadIndex >= 1) ?
                            string.Format(
                                "{0}__ctor_{1}(&{2})",
                                typeName,
                                overloadIndex,
                                parameterString) :
                            string.Format(
                                "{0}__ctor(&{1})",
                                typeName,
                                parameterString)
                        };
                    }
                    else
                    {
                        // ValueType's default constructor not declared.
                        return new[] { string.Format(
                                           "memset(&{0}, 0x00, {1})",
                                           extractContext.GetSymbolName(thisSymbol),
                                           type.CLanguageStaticSizeOfExpression) };
                    }
                }
                // Object reference types.
                else
                {
                    var get = new[]
                    {
                        string.Format(
                            "{0} = il2c_get_uninitialized_object({1})",
                            extractContext.GetSymbolName(thisSymbol),
                            type.MangledName)
                    };

                    var callCtor = new[]
                    {
                        (overloadIndex >= 1) ?
                        string.Format(
                            "{0}__ctor_{1}({2})",
                            type.MangledName,
                            overloadIndex,
                            parameterString) :
                        string.Format(
                            "{0}__ctor({1})",
                            type.MangledName,
                            parameterString)
                    };

                    return get.
                    Concat(callCtor).
                    ToArray();
                }
            });
        }
Example #7
0
        public override ExpressionEmitter Prepare(
            IMethodInformation ctor, DecodeContext decodeContext)
        {
            if (!ctor.IsConstructor)
            {
                throw new InvalidProgramSequenceException(
                          "Invalid new object constructor: Location={0}, Method={1}",
                          decodeContext.CurrentCode.RawLocation,
                          ctor.FriendlyName);
            }

            // Generate the constructor's argument expressions.
            var type = ctor.DeclaringType;
            ILocalVariableInformation thisSymbol = null;

            var pairParameters = new LinkedList <Utilities.RightExpressionGivenParameter>();

            foreach (var parameter in ctor.Parameters.Reverse())
            {
                // Except this parameter
                if (pairParameters.Count < (ctor.Parameters.Length) - 1)
                {
                    pairParameters.AddFirst(new Utilities.RightExpressionGivenParameter(
                                                parameter.TargetType,
                                                decodeContext.PopStack()));
                }
                // "this" parameter
                else
                {
                    Debug.Assert(thisSymbol == null);

                    // Instance from get_uninitialized_object
                    thisSymbol = decodeContext.PushStack(type, ctor);

                    pairParameters.AddFirst(new Utilities.RightExpressionGivenParameter(
                                                type,
                                                thisSymbol));
                }
            }

            Debug.Assert(thisSymbol != null);

            var codeInformation = decodeContext.CurrentCode;

            // Register target constructor declaring type (at the file scope).
            decodeContext.PrepareContext.RegisterType(type, decodeContext.Method);

            // Specialized the delegate type:
            //   We can use for instantiate the delegate instance with "il2c_new_delegate()."
            if (type.IsDelegate)
            {
                if (type.IsAbstract || type.IsDelegateType || type.IsMulticastDelegateType)
                {
                    throw new InvalidProgramSequenceException(
                              "Invalid delegate type: Location={0}, Method={1}",
                              codeInformation.RawLocation,
                              type.FriendlyName);
                }

                if ((ctor.Parameters.Length != 3) ||
                    !ctor.Parameters[1].TargetType.IsObjectType ||
                    !ctor.Parameters[2].TargetType.IsIntPtrType)
                {
                    throw new InvalidProgramSequenceException(
                              "Invalid delegate constructor: Location={0}, Method={1}",
                              codeInformation.RawLocation,
                              ctor.FriendlyName);
                }

                return((extractContext, _) =>
                {
                    var parameterString = Utilities.GetGivenParameterDeclaration(
                        pairParameters.Skip(1).ToArray(), extractContext, codeInformation);

                    return new[]
                    {
                        string.Format(
                            "{0} = il2c_new_delegate({1}, {2})",
                            extractContext.GetSymbolName(thisSymbol),
                            type.MangledUniqueName,
                            parameterString)
                    };
                });
            }

            // Specialized the thread type:
            if (type.UniqueName == "System.Threading.Thread")
            {
                if (!type.IsClass || !type.IsSealed)
                {
                    throw new InvalidProgramSequenceException(
                              "Invalid thread type: Location={0}, Method={1}",
                              codeInformation.RawLocation,
                              type.FriendlyName);
                }

                if ((ctor.Parameters.Length != 2) ||
                    ((ctor.Parameters[1].TargetType.UniqueName != "System.Threading.ThreadStart") &&
                     (ctor.Parameters[1].TargetType.UniqueName != "System.Threading.ParameterizedThreadStart")))
                {
                    throw new InvalidProgramSequenceException(
                              "Invalid thread constructor: Location={0}, Method={1}",
                              codeInformation.RawLocation,
                              ctor.FriendlyName);
                }

                return((extractContext, _) =>
                {
                    var parameterString = Utilities.GetGivenParameterDeclaration(
                        pairParameters.Skip(1).ToArray(), extractContext, codeInformation);

                    return new[]
                    {
                        string.Format(
                            "{0} = il2c_new_thread({1})",
                            extractContext.GetSymbolName(thisSymbol),
                            parameterString)
                    };
                });
            }

            // TODO: overloadIndex
            var overloadIndex = ctor.OverloadIndex;

            return((extractContext, _) =>
            {
                var parameterString = Utilities.GetGivenParameterDeclaration(
                    pairParameters.ToArray(), extractContext, codeInformation);

                // newobj opcode can handle value type with parameter applied constructor.
                if (type.IsValueType)
                {
                    // IL2C can't understand the native type size.
                    // So, the expression will make calculation at the C compiler.
                    var memsetExpression =
                        (type.NativeType != null) ?
                        "memset(&{0}, 0x00, sizeof {0})" :
                        "memset(&{0}, 0x00, {1})";

                    // If constructor's arguments greater than or equal 2 (this and others)
                    if (pairParameters.Count >= 2)
                    {
                        var typeName = type.CLanguageTypeName;
                        return new[] {
                            string.Format(
                                memsetExpression,
                                extractContext.GetSymbolName(thisSymbol),
                                type.CLanguageStaticSizeOfExpression),
                            string.Format(
                                "{0}(&{1})",
                                ctor.CLanguageFunctionFullName,
                                parameterString)
                        };
                    }
                    else
                    {
                        // ValueType's default constructor not declared.
                        return new[] { string.Format(
                                           memsetExpression,
                                           extractContext.GetSymbolName(thisSymbol),
                                           type.MangledUniqueName) };
                    }
                }
                // Object reference types.
                else
                {
                    var get = new[]
                    {
                        string.Format(
                            "{0} = il2c_get_uninitialized_object({1})",
                            extractContext.GetSymbolName(thisSymbol),
                            type.MangledUniqueName)
                    };

                    var callCtor = new[]
                    {
                        string.Format(
                            "{0}({1})",
                            ctor.CLanguageFunctionFullName,
                            parameterString)
                    };

                    return get.
                    Concat(callCtor).
                    ToArray();
                }
            });
        }