/// <summary> /// Optimize expressions /// </summary> public static void Convert(AstBlock ast) { var variableExpressions = ast.GetExpressions().Where(x => x.Operand is AstVariable).ToList(); var allVariables = variableExpressions.Select(x => (AstVariable)x.Operand).Distinct().ToList(); var allStructVariables = allVariables.Where(x => x.Type.IsStruct()).ToList(); var index = 0; foreach (var iterator in allStructVariables) { var variable = iterator; if (variable.IsThis || variable.IsParameter) { continue; } if (variableExpressions.Any(x => (x.Operand == variable) && (x.Code == AstCode.Stloc))) { continue; } // Get struct type var structType = variable.Type.Resolve(); var defaultCtorDef = StructCallConverter.GetDefaultValueCtor(structType); var defaultCtor = variable.Type.CreateReference(defaultCtorDef); // Variable is not initialized var newObjExpr = new AstExpression(ast.SourceLocation, AstCode.Newobj, defaultCtor).SetType(variable.Type); var initExpr = new AstExpression(ast.SourceLocation, AstCode.Stloc, variable, newObjExpr).SetType(variable.Type); ast.Body.Insert(index++, initExpr); } }
/// <summary> /// Perform all dot42 related Ast conversions. /// </summary> public static void Convert(DecompilerContext context, AstBlock ast, MethodSource currentMethod, AssemblyCompiler compiler) { if (ast.IsOptimizedForTarget) { return; } #if DEBUG //Debugger.Launch(); if ((currentMethod.Method != null) && (currentMethod.Method.Name.Equals("runTest", StringComparison.OrdinalIgnoreCase))) { //Debugger.Launch(); } #endif IntPtrConverter.Convert(ast, compiler); TypeOfConverter.Convert(ast, compiler); BranchOptimizer.Convert(ast); CompoundAssignmentConverter.Convert(ast); ByReferenceParamConverter.Convert(context, ast, compiler); CompareUnorderedConverter.Convert(ast); EnumConverter.Convert(ast, compiler); EnumOptimizer.Convert(ast, compiler); // Keep this order NullableConverter.Convert(ast, compiler); PrimitiveAddressOfConverter.Convert(ast, currentMethod, compiler); StructCallConverter.Convert(ast, compiler); // end InitializeStructVariablesConverter.Convert(ast); DelegateConverter.Convert(ast); LdcWideConverter.Convert(ast); LdLocWithConversionConverter.Convert(ast); ConvertAfterLoadConversionConverter.Convert(ast); ConvertBeforeStoreConversionConverter.Convert(ast); CleanupConverter.Convert(ast); GenericsConverter.Convert(ast); // Expand cast expressions CastConverter.Convert(ast, currentMethod, compiler); // Expand generic instance information GenericInstanceConverter.Convert(ast, currentMethod, compiler); }
private static void ConvertUnboxStruct(AstExpression node, XTypeReference resultType, XTypeSystem typeSystem) { // Structs must never be null. We have to handle structs here, since a newobj // might need generic arguments. These would be difficult to provide at "UnboxFromGeneric", // but will be automatically filled in by the GenericInstanceConverter // convert to (temp$ = (T)x) != null ? temp$ : default(T) // replace any unbox, but keep if otherwise. var clone = node.Code == AstCode.Unbox ? new AstExpression(node.Arguments[0]) : new AstExpression(node); // make sure we don't evaluate the expression twice. var tempVar = new AstGeneratedVariable("temp$", "") { Type = typeSystem.Object }; // T(x) var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, resultType, clone) .SetType(resultType); // temporary storage var storeTempVar = new AstExpression(node.SourceLocation, AstCode.Stloc, tempVar, txExpr) { ExpectedType = resultType }; var loadTempVar = new AstExpression(node.SourceLocation, AstCode.Ldloc, tempVar) .SetType(resultType); // default (T) var defaultT = new AstExpression(node.SourceLocation, AstCode.DefaultValue, resultType).SetType(resultType); var constructor = StructCallConverter.GetDefaultValueCtor(resultType.Resolve()); StructCallConverter.ConvertDefaultValue(defaultT, constructor); // Combine var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, resultType, storeTempVar, loadTempVar, defaultT) .SetType(resultType); node.CopyFrom(conditional); }
/// <summary> /// Perform all dot42 related Ast conversions. /// </summary> public static void Convert(DecompilerContext context, AstBlock ast, MethodSource currentMethod, AssemblyCompiler compiler, StopAstConversion stop = StopAstConversion.None) { if (ast.IsOptimizedForTarget) { return; } #if DEBUG //Debugger.Launch(); if ((currentMethod.Method != null) && (currentMethod.Method.Name.Equals("runTest", StringComparison.OrdinalIgnoreCase))) { //Debugger.Launch(); } #endif IntPtrConverter.Convert(ast, compiler); if (stop == StopAstConversion.AfterIntPtrConverter) { return; } TypeOfConverter.Convert(ast, compiler); if (stop == StopAstConversion.AfterTypeOfConverter) { return; } // TODO: check if we actually need this optimizer, as we have a more throughoutful // optimizer as the last step. BranchOptimizer.Convert(ast); if (stop == StopAstConversion.AfterBranchOptimizer) { return; } CompoundAssignmentConverter.Convert(ast); if (stop == StopAstConversion.AfterCompoundAssignmentConverter) { return; } // keep this order FixAsyncStateMachine.Convert(ast, currentMethod, compiler); if (stop == StopAstConversion.AfterFixAsyncStateMachine) { return; } InterlockedConverter.Convert(ast, currentMethod, compiler); if (stop == StopAstConversion.AfterInterlockedConverter) { return; } ByReferenceParamConverter.Convert(context, ast, compiler); if (stop == StopAstConversion.AfterByReferenceParamConverter) { return; } // end CompareUnorderedConverter.Convert(ast); if (stop == StopAstConversion.AfterCompareUnorderedConverter) { return; } EnumConverter.Convert(ast, compiler); if (stop == StopAstConversion.AfterEnumConverter) { return; } EnumOptimizer.Convert(ast, compiler); if (stop == StopAstConversion.AfterEnumOptimizer) { return; } // Keep this order NullableConverter.Convert(ast, compiler); if (stop == StopAstConversion.AfterNullableConverter) { return; } PrimitiveAddressOfConverter.Convert(ast, currentMethod, compiler); if (stop == StopAstConversion.AfterPrimitiveAddressOfConverter) { return; } StructCallConverter.Convert(ast, compiler); if (stop == StopAstConversion.AfterStructCallConverter) { return; } // end InitializeStructVariablesConverter.Convert(ast); if (stop == StopAstConversion.AfterInitializeStructVariablesConverter) { return; } DelegateConverter.Convert(ast); if (stop == StopAstConversion.AfterDelegateConverter) { return; } LdcWideConverter.Convert(ast); if (stop == StopAstConversion.AfterLdcWideConverter) { return; } LdLocWithConversionConverter.Convert(ast); if (stop == StopAstConversion.AfterLdLocWithConversionConverter) { return; } ConvertAfterLoadConversionConverter.Convert(ast); if (stop == StopAstConversion.AfterConvertAfterLoadConversionConverter) { return; } ConvertBeforeStoreConversionConverter.Convert(ast); if (stop == StopAstConversion.AfterConvertBeforeStoreConversionConverter) { return; } CleanupConverter.Convert(ast); if (stop == StopAstConversion.AfterCleanupConverter) { return; } GenericsConverter.Convert(ast, currentMethod, compiler.Module.TypeSystem); if (stop == StopAstConversion.AfterGenericsConverter) { return; } // Expand cast expressions CastConverter.Convert(ast, currentMethod, compiler); if (stop == StopAstConversion.AfterCastConverter) { return; } // Expand generic instance information GenericInstanceConverter.Convert(ast, currentMethod, compiler); if (stop == StopAstConversion.AfterGenericInstanceConverter) { return; } // run the branch optimizer again. (do we need the first invocation?) BranchOptimizer2.Convert(ast, compiler); if (stop == StopAstConversion.AfterBranchOptimizer2) { return; } }