private JSExpression Hoist (JSExpression expression, TypeReference type, List<JSExpression> commaElements) {
            if (expression is JSVariable)
                return null;
            else if (expression is JSLiteral)
                return null;

            var thisBoe = expression as JSBinaryOperatorExpression;
            if ((thisBoe != null) &&
                (thisBoe.Operator == JSOperator.Assignment) &&
                (thisBoe.Left is JSVariable)
            ) {
                // If the value is (x = y), insert 'x = y' and then set the value to 'x'
                commaElements.Add(thisBoe);
                return thisBoe.Left;
            } else {
                var tempVar = new JSRawOutputIdentifier(
                    type, "$temp{0:X2}", Function.TemporaryVariableCount++
                );

                commaElements.Add(new JSBinaryOperatorExpression(
                    JSOperator.Assignment, tempVar, expression, type
                ));

                return tempVar;
            }
        }
Beispiel #2
0
        public void EmitField(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression defaultValue)
        {
            var fieldInfo = Translator.TypeInfoProvider.GetField(field);
            var typeKeyword = WasmUtil.PickTypeKeyword(fieldInfo.FieldType);

            // Unhandled type
            if (typeKeyword == null)
                return;

            Switch(PrecedingType.Global);

            Formatter.WriteRaw("(global ${0} {1})", WasmUtil.EscapeIdentifier(fieldInfo.Name), typeKeyword);
            Formatter.ConditionalNewLine();
        }
Beispiel #3
0
        public void EmitMethodDefinition (
            DecompilerContext context, MethodReference methodRef, MethodDefinition method,
            IAstEmitter astEmitter, bool stubbed,
            JSRawOutputIdentifier dollar, MethodInfo methodInfo = null
        ) {
            if (methodInfo == null)
                methodInfo = TypeInfo.GetMemberInformation<Internal.MethodInfo>(method);

            bool isExternal, isReplaced, methodIsProxied;

            if (!Translator.ShouldTranslateMethodBody(
                method, methodInfo, stubbed,
                out isExternal, out isReplaced, out methodIsProxied
            ))
                return;

            JSFunctionExpression function = Translator.GetFunctionBodyForMethod(
                isExternal, methodInfo
            );

            astEmitter.ReferenceContext.EnclosingType = method.DeclaringType;
            astEmitter.ReferenceContext.EnclosingMethod = null;

            Formatter.NewLine();

            astEmitter.ReferenceContext.Push();
            astEmitter.ReferenceContext.DefiningMethod = methodRef;

            try {
                dollar.WriteTo(Formatter);
                Formatter.Dot();
                if (methodInfo.IsPInvoke)
                    // FIXME: Write out dll name from DllImport
                    // FIXME: Write out alternate method name if provided
                    Formatter.Identifier("PInvokeMethod", EscapingMode.None);
                else if (isExternal && !Configuration.GenerateSkeletonsForStubbedAssemblies.GetValueOrDefault(false))
                    Formatter.Identifier("ExternalMethod", EscapingMode.None);
                else
                    Formatter.Identifier("Method", EscapingMode.None);
                Formatter.LPar();

                // FIXME: Include IsVirtual?
                Formatter.MemberDescriptor(method.IsPublic, method.IsStatic, method.IsVirtual, false);

                Formatter.Comma();
                Formatter.Value(Util.EscapeIdentifier(methodInfo.GetName(true), EscapingMode.String));

                Formatter.Comma();
                Formatter.NewLine();

                Formatter.MethodSignature(methodRef, methodInfo.Signature, astEmitter.ReferenceContext);

                if (methodInfo.IsPInvoke && method.HasPInvokeInfo) {
                    Formatter.Comma();
                    Formatter.NewLine();
                    EmitPInvokeInfo(
                        methodRef, method, astEmitter
                    );
                } else if (!isExternal) {
                    Formatter.Comma();
                    Formatter.NewLine();

                    if (function != null) {
                        Formatter.WriteRaw(Util.EscapeIdentifier(function.DisplayName));
                    } else {
                        Formatter.Identifier("JSIL.UntranslatableFunction", EscapingMode.None);
                        Formatter.LPar();
                        Formatter.Value(method.FullName);
                        Formatter.RPar();
                    }
                }

                Formatter.NewLine();
                Formatter.RPar();

                astEmitter.ReferenceContext.AttributesMethod = methodRef;

                EmitOverrides(context, methodInfo.DeclaringType, method, methodInfo, astEmitter);

                EmitCustomAttributes(context, method.DeclaringType, method, astEmitter);

                EmitParameterAttributes(context, method.DeclaringType, method, astEmitter);

                Formatter.Semicolon();
            } finally {
                astEmitter.ReferenceContext.Pop();
            }
        }
Beispiel #4
0
        public void EmitPrimitiveDefinition (
            DecompilerContext context, TypeDefinition typedef, bool stubbed, JSRawOutputIdentifier dollar
        ) {
            bool isIntegral = false;
            bool isNumeric = false;

            switch (typedef.FullName) {
                case "System.Boolean":
                    isIntegral = true;
                    isNumeric = true;
                    break;
                case "System.Char":
                    isIntegral = true;
                    isNumeric = true;
                    break;
                case "System.Byte":
                case "System.SByte":
                case "System.UInt16":
                case "System.Int16":
                case "System.UInt32":
                case "System.Int32":
                case "System.UInt64":
                case "System.Int64":
                    isIntegral = true;
                    isNumeric = true;
                    break;
                case "System.Single":
                case "System.Double":
                case "System.Decimal":
                    isIntegral = false;
                    isNumeric = true;
                    break;
            }

            var setValue = (Action<string, bool>)((name, value) => {
                dollar.WriteTo(Formatter);
                Formatter.Dot();
                Formatter.Identifier("SetValue", EscapingMode.None);
                Formatter.LPar();
                Formatter.Value(name);
                Formatter.Comma();
                Formatter.Value(value);
                Formatter.RPar();
                Formatter.Semicolon(true);
            });

            setValue("__IsIntegral__", isIntegral);
            setValue("__IsNumeric__", isNumeric);
        }
Beispiel #5
0
        private void EmitFieldOrConstant (
            DecompilerContext context, IAstEmitter astEmitter, 
            FieldDefinition field, JSRawOutputIdentifier dollar, 
            JSExpression defaultValue, bool isConstant
        ) {
            var fieldInfo = TypeInfo.GetMemberInformation<Internal.FieldInfo>(field);
            if ((fieldInfo == null) || fieldInfo.IsIgnored)
                return;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();
            Formatter.Identifier(
                isConstant 
                    ? "Constant"
                    : "Field", EscapingMode.None
            );
            Formatter.LPar();

            Formatter.MemberDescriptor(
                field.IsPublic, fieldInfo.IsStatic,
                isReadonly: field.IsInitOnly,
                offset: field.DeclaringType.IsExplicitLayout 
                    ? (int?)field.Offset 
                    : null
            );

            Formatter.Comma();

            var fieldName = Util.EscapeIdentifier(fieldInfo.Name, EscapingMode.MemberIdentifier);

            Formatter.Value(fieldName);

            Formatter.Comma();

            Formatter.TypeReference(fieldInfo.FieldType, astEmitter.ReferenceContext);

            if (defaultValue != null) {
                Formatter.Comma();
                astEmitter.Emit(defaultValue);
            }

            Formatter.RPar();

            EmitCustomAttributes(context, field.DeclaringType, field, astEmitter);

            Formatter.Semicolon();
        }
Beispiel #6
0
 public void EmitConstant (DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression value) {
     EmitFieldOrConstant(context, astEmitter, field, dollar, value, true);
 }
Beispiel #7
0
 public Identifier (string text, JSRawOutputIdentifier @object) {
     Text = text;
     Object = @object;
 }
Beispiel #8
0
        public void EmitInterfaceList (
            TypeInfo typeInfo, 
            IAstEmitter astEmitter,
            JSRawOutputIdentifier dollar
        ) {
            var interfaces = typeInfo.AllInterfacesRecursive;
            if (interfaces.Count <= 0)
                return;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();
            Formatter.Identifier("ImplementInterfaces", EscapingMode.None);
            Formatter.LPar();

            bool firstInterface = true;

            for (var i = 0; i < interfaces.Count; i++) {
                var elt = interfaces.Array[interfaces.Offset + i];
                if (elt.ImplementingType != typeInfo)
                    continue;
                if (elt.ImplementedInterface.Info.IsIgnored)
                    continue;
                if (Translator.ShouldSkipMember(elt.ImplementedInterface.Reference))
                    continue;

                var @interface = elt.ImplementedInterface.Reference;

                if (firstInterface)
                    firstInterface = false;
                else
                    Formatter.Comma();

                Formatter.NewLine();

                Formatter.Comment("{0}", i);
                Formatter.TypeReference(@interface, astEmitter.ReferenceContext);
            }

            Formatter.NewLine();
            Formatter.RPar();
            Formatter.Semicolon(true);
        }
 public void EmitField(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression defaultValue)
 {
 }
Beispiel #10
0
 public void EmitEvent(DecompilerContext context, IAstEmitter astEmitter, EventDefinition @event, JSRawOutputIdentifier dollar)
 {
 }
Beispiel #11
0
 public void EmitPrimitiveDefinition(DecompilerContext context, TypeDefinition typedef, bool stubbed, JSRawOutputIdentifier dollar)
 {
 }
Beispiel #12
0
 public void EmitProperty(DecompilerContext context, IAstEmitter astEmitter, PropertyDefinition property, JSRawOutputIdentifier dollar)
 {
 }
Beispiel #13
0
        public void EmitMethodDefinition(DecompilerContext context, MethodReference methodRef, MethodDefinition method, IAstEmitter astEmitter, bool stubbed, JSRawOutputIdentifier dollar, MethodInfo methodInfo = null)
        {
            // Skip Main() and emit it at the footer
            if (Assembly.EntryPoint == method) {
                // HACK: Store this so we can use it to emit the entry point's body later
                EntryPointAstEmitter = astEmitter;
                return;
            }

            var name = WasmUtil.FormatMemberName(method);

            var sExport = "Wasm.Module.ExportAttribute";

            methodInfo = methodInfo ?? Translator.TypeInfoProvider.GetMethod(methodRef);

            if (methodInfo != null && methodInfo.Metadata.HasAttribute(sExport)) {
                var exportName = method.Name;
                var ap = methodInfo.Metadata.GetAttributeParameters(sExport);
                if ((ap.Count == 1) && (ap[0].Value is string))
                    exportName = (string)ap[0].Value;

                Switch(PrecedingType.Export);

                Formatter.WriteRaw("(export \"{0}\" ${1})", exportName, name);
                Formatter.ConditionalNewLine();
            }
        }
Beispiel #14
0
 public void EmitInterfaceList(TypeInfo typeInfo, IAstEmitter astEmitter, JSRawOutputIdentifier dollar)
 {
 }
Beispiel #15
0
        public void EmitField(DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression defaultValue)
        {
            var fieldInfo = Translator.TypeInfoProvider.GetField(field);
            var typeKeyword = WasmUtil.PickTypeKeyword(fieldInfo.FieldType);

            // Unhandled type
            if (typeKeyword == null)
                return;

            GetFieldOffset(field);
        }
Beispiel #16
0
        public void EmitProperty (
            DecompilerContext context, IAstEmitter astEmitter,
            PropertyDefinition property, JSRawOutputIdentifier dollar
        ) {
            if (Translator.ShouldSkipMember(property))
                return;

            var propertyInfo = TypeInfo.GetMemberInformation<Internal.PropertyInfo>(property);
            if ((propertyInfo == null) || propertyInfo.IsIgnored)
                return;

            var isStatic = (property.SetMethod ?? property.GetMethod).IsStatic;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();

            if (propertyInfo.IsExternal)
                Formatter.Identifier("ExternalProperty", EscapingMode.None);
            else if (property.DeclaringType.HasGenericParameters && isStatic)
                Formatter.Identifier("GenericProperty", EscapingMode.None);
            else
                Formatter.Identifier("Property", EscapingMode.None);

            Formatter.LPar();

            Formatter.MemberDescriptor(propertyInfo.IsPublic, propertyInfo.IsStatic, propertyInfo.IsVirtual);

            Formatter.Comma();

            Formatter.Value(Util.EscapeIdentifier(propertyInfo.Name, EscapingMode.String));

            Formatter.Comma();
            Formatter.TypeReference(property.PropertyType, astEmitter.ReferenceContext);

            Formatter.RPar();

            EmitCustomAttributes(context, property.DeclaringType, property, astEmitter);

            Formatter.Semicolon();
        }
Beispiel #17
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type = uoe.Expression.GetActualType(TypeSystem);
            var isEnum = IsEnumOrNullableEnum(type);

            if (isEnum) {
                var castToInt = JSInvocationExpression.InvokeMethod(
                    JS.valueOf(TypeSystem.Int32), uoe.Expression, null, true
                );

                if (LogicalOperators.Contains(uoe.Operator)) {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                } else if (uoe.Operator == JSOperator.Negation) {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                } else if (uoe.Operator is JSUnaryMutationOperator) {
                    if (
                        (uoe.Operator == JSOperator.PreIncrement) ||
                        (uoe.Operator == JSOperator.PreDecrement)
                    ) {
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PreDecrement)
                                ? JSOperator.Subtract
                                : JSOperator.Add,
                            type
                        );

                        ParentNode.ReplaceChild(uoe, assignment);
                        VisitReplacement(assignment);
                        return;

                    } else if (
                        (uoe.Operator == JSOperator.PostIncrement) ||
                        (uoe.Operator == JSOperator.PostDecrement)
                    ) {
                        // FIXME: Terrible hack oh god (also not strict mode safe)
                        var tempVariable = new JSRawOutputIdentifier(
                            (output) => output.WriteRaw("$temp"), type
                        );
                        var makeTempCopy = new JSBinaryOperatorExpression(
                            JSOperator.Assignment, tempVariable, uoe.Expression, type
                        );
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PostDecrement)
                                ? JSOperator.Subtract
                                : JSOperator.Add,
                            type
                        );

                        var comma = new JSCommaExpression(
                            makeTempCopy,
                            assignment,
                            tempVariable
                        );

                        ParentNode.ReplaceChild(uoe, comma);
                        VisitReplacement(comma);
                        return;

                    } else {
                        throw new NotImplementedException("Unary mutation of enum not supported: " + uoe.ToString());
                    }
                }
            }

            VisitChildren(uoe);
        }
Beispiel #18
0
        public void EmitEvent (
            DecompilerContext context, IAstEmitter astEmitter, 
            EventDefinition @event, JSRawOutputIdentifier dollar
        ) {
            if (Translator.ShouldSkipMember(@event))
                return;

            var eventInfo = TypeInfo.GetMemberInformation<Internal.EventInfo>(@event);
            if ((eventInfo == null) || eventInfo.IsIgnored)
                return;

            var isStatic = (@event.AddMethod ?? @event.RemoveMethod).IsStatic;

            Formatter.NewLine();

            dollar.WriteTo(Formatter);
            Formatter.Dot();

            if (eventInfo.IsExternal)
                Formatter.Identifier("ExternalEvent", EscapingMode.None);
            else if (@event.DeclaringType.HasGenericParameters && isStatic)
                Formatter.Identifier("GenericEvent", EscapingMode.None);
            else
                Formatter.Identifier("Event", EscapingMode.None);

            Formatter.LPar();

            Formatter.MemberDescriptor(eventInfo.IsPublic, eventInfo.IsStatic, eventInfo.IsVirtual);

            Formatter.Comma();

            Formatter.Value(Util.EscapeIdentifier(eventInfo.Name, EscapingMode.String));

            Formatter.Comma();
            Formatter.TypeReference(@event.EventType, astEmitter.ReferenceContext);

            Formatter.RPar();

            EmitCustomAttributes(context, @event.DeclaringType, @event, astEmitter);

            Formatter.Semicolon();
        }
Beispiel #19
0
 public void EmitMethodDefinition(DecompilerContext context, MethodReference methodRef, MethodDefinition method, IAstEmitter astEmitter, bool stubbed, JSRawOutputIdentifier dollar, MethodInfo methodInfo = null)
 {
 }