diff --git a/Cecilifier.Core.Tests/Framework/AssemblyDiff/AssemblyComparer.cs b/Cecilifier.Core.Tests/Framework/AssemblyDiff/AssemblyComparer.cs index 246c2de4..bf97d974 100644 --- a/Cecilifier.Core.Tests/Framework/AssemblyDiff/AssemblyComparer.cs +++ b/Cecilifier.Core.Tests/Framework/AssemblyDiff/AssemblyComparer.cs @@ -393,7 +393,7 @@ private static bool EqualOrEquivalent(Instruction instruction, Instruction curre case Code.Stloc_1: return current.OpCode.Code == Code.Stloc && VarIndex(current.Operand) == 1; case Code.Stloc_2: return current.OpCode.Code == Code.Stloc && VarIndex(current.Operand) == 2; case Code.Stloc_3: return current.OpCode.Code == Code.Stloc && VarIndex(current.Operand) == 3; - + case Code.Ldarga_S: return current.OpCode.Code == Code.Ldarga; case Code.Ldarg_S: return current.OpCode.Code == Code.Ldarg; diff --git a/Cecilifier.Core.Tests/Framework/ResourceTestBase.cs b/Cecilifier.Core.Tests/Framework/ResourceTestBase.cs index e6551a6a..aeb904b5 100644 --- a/Cecilifier.Core.Tests/Framework/ResourceTestBase.cs +++ b/Cecilifier.Core.Tests/Framework/ResourceTestBase.cs @@ -30,7 +30,7 @@ protected void AssertResourceTestBinary(string resourceBasePath, TestKind kind) AssertResourceTest(actualAssemblyPath, expectedAssemblyPath, tbc); } - protected void AssertResourceTestWithExplictExpectation(string resourceName, string methodSignature) + protected void AssertResourceTestWithExplicitExpectation(string resourceName, string methodSignature) { using (var tbc = ReadResource(resourceName, "cs", TestKind.Integration)) using (var expectedILStream = ReadResource(resourceName, "cs.il", TestKind.Integration)) diff --git a/Cecilifier.Core.Tests/Tests/Integration/CodeBlock.cs b/Cecilifier.Core.Tests/Tests/Integration/CodeBlock.cs index f933d19d..0700935d 100644 --- a/Cecilifier.Core.Tests/Tests/Integration/CodeBlock.cs +++ b/Cecilifier.Core.Tests/Tests/Integration/CodeBlock.cs @@ -1,47 +1,47 @@ -using NUnit.Framework; - -namespace Cecilifier.Core.Tests.Integration -{ - [TestFixture] - public class BlockTestCase : IntegrationResourceBasedTest - { - [Test] - public void IfStatementTest() - { - AssertResourceTestWithExplictExpectation(@"CodeBlock/Conditional/IfStatement", "System.Void IfStatement::Foo(System.Int32)"); - } - - [Test] - public void IfThenElseStatementTest() - { - AssertResourceTestWithExplictExpectation(@"CodeBlock/Conditional/IfThenElseStatement", "System.Void IfThenElseStatement::Foo(System.Int32)"); - } - - [Test] - public void NestedIfStatementTest() - { - AssertResourceTestWithExplictExpectation(@"CodeBlock/Conditional/NestedIfStatement", "System.Void NestedIfStatement::Foo(System.Int32)"); - } - - [Test] - [Ignore("Not Implemented yet")] - public void NonVirtualMethodCallTest() - { - AssertResourceTest(@"CodeBlock/MethodCall/NonVirtualMethodCall"); - } - - [Test] - [Ignore("Not Implemented yet")] - public void NullCoalescingTest() - { - AssertResourceTest(@"CodeBlock/Conditional/"); - } - - [Test] - [Ignore("Not Implemented yet")] - public void SwitchStatementTest() - { - AssertResourceTest(@"CodeBlock/Conditional/"); - } - } -} +using NUnit.Framework; + +namespace Cecilifier.Core.Tests.Integration +{ + [TestFixture] + public class BlockTestCase : IntegrationResourceBasedTest + { + [Test] + public void IfStatementTest() + { + AssertResourceTestWithExplicitExpectation(@"CodeBlock/Conditional/IfStatement", "System.Void IfStatement::Foo(System.Int32)"); + } + + [Test] + public void IfThenElseStatementTest() + { + AssertResourceTestWithExplicitExpectation(@"CodeBlock/Conditional/IfThenElseStatement", "System.Void IfThenElseStatement::Foo(System.Int32)"); + } + + [Test] + public void NestedIfStatementTest() + { + AssertResourceTestWithExplicitExpectation(@"CodeBlock/Conditional/NestedIfStatement", "System.Void NestedIfStatement::Foo(System.Int32)"); + } + + [Test] + [Ignore("Not Implemented yet")] + public void NonVirtualMethodCallTest() + { + AssertResourceTest(@"CodeBlock/MethodCall/NonVirtualMethodCall"); + } + + [Test] + [Ignore("Not Implemented yet")] + public void NullCoalescingTest() + { + AssertResourceTest(@"CodeBlock/Conditional/"); + } + + [Test] + [Ignore("Not Implemented yet")] + public void SwitchStatementTest() + { + AssertResourceTest(@"CodeBlock/Conditional/"); + } + } +} diff --git a/Cecilifier.Core.Tests/Tests/Integration/ExpressionTestCase.cs b/Cecilifier.Core.Tests/Tests/Integration/ExpressionTestCase.cs index ca87489a..ec62c39d 100644 --- a/Cecilifier.Core.Tests/Tests/Integration/ExpressionTestCase.cs +++ b/Cecilifier.Core.Tests/Tests/Integration/ExpressionTestCase.cs @@ -20,7 +20,7 @@ public void TestLocalVariableAssignment() [Test] public void TestMultipleLocalVariableAssignment() { - AssertResourceTestWithExplictExpectation(@"Expressions/MultipleLocalVariableAssignment", "System.Void MultipleLocalVariableAssignment::Method(System.Int32,System.String)"); + AssertResourceTestWithExplicitExpectation(@"Expressions/MultipleLocalVariableAssignment", "System.Void MultipleLocalVariableAssignment::Method(System.Int32,System.String)"); } [Test] @@ -44,7 +44,7 @@ public void TestAdd() [Test] public void TestAdd2() { - AssertResourceTestWithExplictExpectation(@"Expressions/Operators/Add2", "System.Void AddOperations2::IntegerString(System.String,System.Int32)"); + AssertResourceTestWithExplicitExpectation(@"Expressions/Operators/Add2", "System.Void AddOperations2::IntegerString(System.String,System.Int32)"); } [Test] @@ -68,7 +68,7 @@ public void TestTernaryOperator() [Test] public void TestTypeInferenceInDeclarations() { - AssertResourceTestWithExplictExpectation(@"Expressions/TypeInferenceInDeclarations", "System.Void TypeInferenceInDeclarations::Foo()"); + AssertResourceTestWithExplicitExpectation(@"Expressions/TypeInferenceInDeclarations", "System.Void TypeInferenceInDeclarations::Foo()"); } [Test] diff --git a/Cecilifier.Core.Tests/Tests/Integration/TryCatchFinallyTestCase.cs b/Cecilifier.Core.Tests/Tests/Integration/TryCatchFinallyTestCase.cs index b421be96..df81dbd6 100644 --- a/Cecilifier.Core.Tests/Tests/Integration/TryCatchFinallyTestCase.cs +++ b/Cecilifier.Core.Tests/Tests/Integration/TryCatchFinallyTestCase.cs @@ -16,7 +16,7 @@ public void TestExceptionHandlers(string testName, bool compareWithExplicitIL = { if (compareWithExplicitIL) { - AssertResourceTestWithExplictExpectation($"TryCatchFinally/{testName}", $"System.Void {testName}::Foo(System.Int32)"); + AssertResourceTestWithExplicitExpectation($"TryCatchFinally/{testName}", $"System.Void {testName}::Foo(System.Int32)"); } else { diff --git a/Cecilifier.Core/AST/AssignmentVisitor.cs b/Cecilifier.Core/AST/AssignmentVisitor.cs index 4d411ee7..d2937d26 100644 --- a/Cecilifier.Core/AST/AssignmentVisitor.cs +++ b/Cecilifier.Core/AST/AssignmentVisitor.cs @@ -11,9 +11,10 @@ internal class AssignmentVisitor : SyntaxWalkerBase { private readonly string ilVar; - internal AssignmentVisitor(IVisitorContext ctx, string ilVar) : base(ctx) + internal AssignmentVisitor(IVisitorContext ctx, string ilVar, AssignmentExpressionSyntax node) : base(ctx) { this.ilVar = ilVar; + PreProcessRefOutAssignments(node.Left); } public LinkedListNode InstrutionPreceedingValueToLoad { get; set; } @@ -109,7 +110,7 @@ private void ParameterAssignment(IParameterSymbol parameter) } } - public void PreProcessRefOutAssignments(ExpressionSyntax node) + void PreProcessRefOutAssignments(ExpressionSyntax node) { var paramSymbol = ParameterVisitor.Process(Context, node); if (paramSymbol != null && paramSymbol.RefKind != RefKind.None) diff --git a/Cecilifier.Core/AST/ExpressionVisitor.cs b/Cecilifier.Core/AST/ExpressionVisitor.cs index 71baaa0b..dc882eea 100644 --- a/Cecilifier.Core/AST/ExpressionVisitor.cs +++ b/Cecilifier.Core/AST/ExpressionVisitor.cs @@ -138,9 +138,8 @@ public override void VisitAssignmentExpression(AssignmentExpressionSyntax node) return; } - var visitor = new AssignmentVisitor(Context, ilVar); - visitor.PreProcessRefOutAssignments(node.Left); - + var visitor = new AssignmentVisitor(Context, ilVar, node); + visitor.InstrutionPreceedingValueToLoad = Context.CurrentLine; Visit(node.Right); if (!valueTypeNoArgObjCreation) @@ -517,15 +516,11 @@ private void ProcessLocalVariable(SimpleNameSyntax localVar, SymbolInfo varInfo) { var symbol = (ILocalSymbol) varInfo.Symbol; var localVarParent = (CSharpSyntaxNode) localVar.Parent; - if ((symbol.Type.IsValueType && localVarParent.Accept(new UsageVisitor()) == UsageKind.CallTarget) || localVarParent.IsKind(SyntaxKind.AddressOfExpression)) + if (HandleLoadAddress(ilVar, symbol.Type, localVarParent, OpCodes.Ldloca, symbol.Name, MemberKind.LocalVariable)) { - AddCilInstruction(ilVar, OpCodes.Ldloca, Context.DefinitionVariables.GetVariable(symbol.Name, MemberKind.LocalVariable).VariableName); - if (localVarParent.IsKind(SyntaxKind.AddressOfExpression)) - AddCilInstruction(ilVar, OpCodes.Conv_U); return; } - AddCilInstruction(ilVar, OpCodes.Ldloc, Context.DefinitionVariables.GetVariable(symbol.Name, MemberKind.LocalVariable).VariableName); HandlePotentialDelegateInvocationOn(localVar, symbol.Type, ilVar); } diff --git a/Cecilifier.Core/AST/MethodDeclarationVisitor.cs b/Cecilifier.Core/AST/MethodDeclarationVisitor.cs index ec606db9..653fed8b 100644 --- a/Cecilifier.Core/AST/MethodDeclarationVisitor.cs +++ b/Cecilifier.Core/AST/MethodDeclarationVisitor.cs @@ -102,7 +102,7 @@ protected void ProcessMethodDeclaration(T node, string simpleName, string fqN } } - protected static string DeclaringTypeNameFor(T node) where T : BaseMethodDeclarationSyntax + private static string DeclaringTypeNameFor(T node) where T : BaseMethodDeclarationSyntax { var declaringType = (TypeDeclarationSyntax) node.Parent; return declaringType.Identifier.ValueText; diff --git a/Cecilifier.Core/AST/SyntaxWalkerBase.cs b/Cecilifier.Core/AST/SyntaxWalkerBase.cs index 4b315dd4..5006ee14 100644 --- a/Cecilifier.Core/AST/SyntaxWalkerBase.cs +++ b/Cecilifier.Core/AST/SyntaxWalkerBase.cs @@ -295,16 +295,11 @@ protected INamedTypeSymbol GetSpecialType(SpecialType specialType) protected void ProcessParameter(string ilVar, SimpleNameSyntax node, IParameterSymbol paramSymbol) { var parent = (CSharpSyntaxNode) node.Parent; - //TODO: Get rid of code duplication in ExpressionVisitor.ProcessLocalVariable(IdentifierNameSyntax localVar, SymbolInfo varInfo) - if ((paramSymbol.Type.IsValueType && parent.Accept(new UsageVisitor()) == UsageKind.CallTarget) || node.Parent.IsKind(SyntaxKind.AddressOfExpression)) + if (HandleLoadAddress(ilVar, paramSymbol.Type, parent, OpCodes.Ldarga, paramSymbol.Name, MemberKind.Parameter)) { - AddCilInstruction(ilVar, OpCodes.Ldarga, Context.DefinitionVariables.GetVariable(paramSymbol.Name, MemberKind.Parameter).VariableName); - if (node.Parent.IsKind(SyntaxKind.AddressOfExpression)) - AddCilInstruction(ilVar, OpCodes.Conv_U); return; } - var method = paramSymbol.ContainingSymbol as IMethodSymbol; if (node.Parent.Kind() == SyntaxKind.SimpleMemberAccessExpression && paramSymbol.ContainingType.IsValueType) { AddCilInstruction(ilVar, OpCodes.Ldarga, Context.DefinitionVariables.GetVariable(paramSymbol.Name, MemberKind.Parameter).VariableName); @@ -316,6 +311,7 @@ protected void ProcessParameter(string ilVar, SimpleNameSyntax node, IParameterS } else { + var method = paramSymbol.ContainingSymbol as IMethodSymbol; OpCode[] optimizedLdArgs = {OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3}; var loadOpCode = optimizedLdArgs[paramSymbol.Ordinal + (method.IsStatic ? 0 : 1)]; AddCilInstruction(ilVar, loadOpCode); @@ -323,6 +319,20 @@ protected void ProcessParameter(string ilVar, SimpleNameSyntax node, IParameterS } } + protected bool HandleLoadAddress(string ilVar, ITypeSymbol symbol, CSharpSyntaxNode parent, OpCode opCode, string symbolName, MemberKind memberKind) + { + if ((symbol.IsValueType && parent.Accept(new UsageVisitor()) == UsageKind.CallTarget) || parent.IsKind(SyntaxKind.AddressOfExpression)) + { + AddCilInstruction(ilVar, opCode, Context.DefinitionVariables.GetVariable(symbolName, memberKind).VariableName); + if (parent.IsKind(SyntaxKind.AddressOfExpression)) + AddCilInstruction(ilVar, OpCodes.Conv_U); + + return true; + } + + return false; + } + protected void HandlePotentialDelegateInvocationOn(SimpleNameSyntax node, ITypeSymbol typeSymbol, string ilVar) { var invocation = node.Parent as InvocationExpressionSyntax;