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; } }
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(); }
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(); } }
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); }
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(); }
public void EmitConstant (DecompilerContext context, IAstEmitter astEmitter, FieldDefinition field, JSRawOutputIdentifier dollar, JSExpression value) { EmitFieldOrConstant(context, astEmitter, field, dollar, value, true); }
public Identifier (string text, JSRawOutputIdentifier @object) { Text = text; Object = @object; }
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) { }
public void EmitEvent(DecompilerContext context, IAstEmitter astEmitter, EventDefinition @event, JSRawOutputIdentifier dollar) { }
public void EmitPrimitiveDefinition(DecompilerContext context, TypeDefinition typedef, bool stubbed, JSRawOutputIdentifier dollar) { }
public void EmitProperty(DecompilerContext context, IAstEmitter astEmitter, PropertyDefinition property, JSRawOutputIdentifier dollar) { }
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(); } }
public void EmitInterfaceList(TypeInfo typeInfo, IAstEmitter astEmitter, JSRawOutputIdentifier dollar) { }
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); }
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(); }
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); }
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(); }
public void EmitMethodDefinition(DecompilerContext context, MethodReference methodRef, MethodDefinition method, IAstEmitter astEmitter, bool stubbed, JSRawOutputIdentifier dollar, MethodInfo methodInfo = null) { }